리눅스를 처음 배우면 이런 말들을 자주 듣는다.
- "ls는 프로그램이다."
- "명령어를 실행하면 프로세스가 생긴다."
- "cd는 프로세스가 아니라 쉘 내부 기능이다."
처음엔 다 비슷하게 들리는데, 사실 이 차이를 정확히 이해하면
리눅스/운영체제 공부가 훨씬 쉬워진다.
이 글에서는 cd , ls , cat , echo , rm 같은 대표 명령어를 예로 들어
명령어(command) / 프로그램(program) / 프로세스(process) 를
깔끔하게 정리해본다.
1. 명령어(command), 프로그램(program), 프로세스(process) 차이
1) 명령어(command)
사용자가 쉘(터미널)에 입력하는 문자열이다.
예를 들어 내가 터미널에 아래를 입력했다면,
ls -l
여기서 ls -l 은 사용자가 입력한 명령어다.
즉, 텍스트(문자열)로 된 "지시"다.
2) 프로그램(program)
디스크에 저장된 실행 파일이다. 예를 들어 ls 는 보통 아래 경로에 존재한다.
/usr/bin/ls
즉, ls 라는 이름의 명령어는
실제로는 /usr/bin/ls 라는 실행 파일(프로그램)을 가리킨다.
이 프로그램은 "코드와 데이터"가 파일 형태로 저장된 정적인 상태다.
실행하지 않으면 그저 파일일 뿐이다.
3) 프로세스(process)
프로그램이 메모리에 올라가 실행 중인 상태다.
ls -l 을 실행하면,
운영체제는 /usr/bin/ls 프로그램을 메모리에 적재하고 실행한다.
이때 생기는 실행 단위를 프로세스라고 한다.
프로세스는 보통 PID(Process ID)를 갖는다.
정리하면 이 흐름이 핵심이다.
명령어(문자열)를 입력하면
→ 쉘이 프로그램(실행 파일)을 찾아 실행하고
→ 실행 중인 프로그램은 프로세스가 된다.
2. "명령어가 실행될 때 프로세스가 된다"는 말의 정확한 의미
조금 더 엄밀히 말하면, "명령어"가 프로세스가 되는 게 아니라:
- 명령어가 가리키는 프로그램이
- 운영체제에 의해 실행되어
- 프로세스가 된다.
즉, 프로세스는 "실행된 프로그램"이다.
3. ls , cat , rm 은 보통 "외부 프로그램"이다
대표적으로 ls , cat , rm 은 대부분의 리눅스에서
/usr/bin 아래에 있는 실행 파일이다.
확인 방법: type , which
type ls
which ls
- type ls 는 ls 가 외부 프로그램인지, 쉘 내장(builtin)인지 알려준다.
- which ls 는 ls 실행 파일이 어디 있는지 보여준다.
보통은 이런 결과가 나온다.
- ls is aliased to ... (alias가 걸려있을 수도 있고)
- ls is /usr/bin/ls
즉 ls 는 실제 실행 파일이 존재하고, 실행하면 프로세스로 실행된다.
4. 그런데 cd 는 왜 다르다고 할까?
cd 는 정말 중요하다. 많은 초보자가 여기서 한 번 헷갈린다.
1) cd 는 보통 "쉘 builtin"이다
cd는 디렉터리를 바꾸는 기능인데,
이 기능은 현재 쉘 프로세스의 작업 디렉터리를 바꿔야 의미가 있다.
만약 cd 가 /usr/bin/cd 같은 외부 프로그램이라면 어떤 문제가 생길까?
- 쉘이 cd 를 실행하기 위해 새 프로세스를 만든다.
- 새 프로세스에서 디렉터리를 바꾼다.
- 프로세스가 종료된다.
- 원래 쉘은 그대로다.
즉, "디렉터리를 바꿨는데도 터미널의 위치가 안 바뀌는" 이상한 상황이 된다.
그래서 cd 는 현재 쉘 안에서 직접 실행되는 내장 명령(builtin) 이어야 한다.
2) 확인해보기
type cd
대부분 이런 결과가 나온다.
cd is a shell builtin
정리하면:
- cd 는 명령어이긴 하지만, 보통 외부 실행 파일이 아니라 쉘 내부 기능
- 실행 시 새 프로세스를 만들지 않고 현재 쉘 프로세스가 직접 처리
5. echo 는 프로그램일까? builtin일까?
echo 는 재미있는 케이스다. 환경에 따라 다를 수 있다.
- 많은 쉘에서 echo 는 builtin이다.
- 동시에 /usr/bin/echo 같은 외부 프로그램도 존재할 수 있다.
확인
type echo
which echo
- type echo 에서 builtin이라고 나오면, 보통 별도 프로세스 없이 쉘이 처리한다.
- \echo 처럼 백슬래시를 붙이면 alias/builtin을 우회하는 경우도 있다.
- /usr/bin/echo 를 직접 호출하면 외부 프로그램 프로세스가 실행된다.
즉 echo 는 "항상 프로그램/항상 프로세스"라고 단정하기 어렵고,
어떤 echo를 쓰느냐가 중요하다.
6. 프로세스가 생기는 순간: 쉘은 무엇을 할까?
외부 프로그램( ls , cat , rm 등)을 실행할 때,
쉘은 보통 이런 흐름으로 동작한다.
- 사용자가 명령어 입력
- 쉘이 파싱(parsing)
- 리다이렉션 설정(필요하면 파일 디스크립터 변경)
- 새 프로세스 생성( fork )
- 새 프로세스가 프로그램 실행( exec )
- 프로그램 종료 후 쉘로 복귀
여기서 중요한 건:
- 리다이렉션( > , < , 2> , 2>&1 등)은 보통 프로그램 실행 전에 쉘이 설정
- 그래서 프로그램 입장에서는 "그냥 stdout/stderr에 출력했을 뿐"인데, 실제로는 파일로 들어간다.
7. 한 장 표로 정리: cd, ls, cat, echo, rm
| 명령어 | 보통 정체 | 실행 파일 존재? | 실행 시 프로세스 생성? |
| cd | 쉘 builtin | 보통 없음 | 보통 X (현재 쉘이 처리) |
| ls | 외부 프로그램 | /usr/bin/ls | O |
| cat | 외부 프로그램 | /usr/bin/cat | O |
| rm | 외부 프로그램 | /usr/bin/rm | O |
| echo | builtin 또는 외부 | /usr/bin/echo 있을 수 있음 | 상황에 따라 O/X |
8. 마무리: "명령어"를 보면 무엇을 떠올리면 좋을까?
리눅스에서 어떤 명령어를 봤을 때 이렇게 생각하면 헷갈림이 확 줄어든다.
- 내가 입력한 건 "명령어 문자열"이다.
- 이 명령어가 가리키는 대상은:
- 외부 프로그램일 수도 있고 ( /usr/bin/... )
- 쉘 builtin일 수도 있다.
- 외부 프로그램이면:
- 실행 순간 운영체제가 프로세스를 만든다.
- builtin이면:
- 현재 쉘 프로세스가 내부적으로 처리한다.
이 관점으로 보면 cd 가 왜 특별한지,
리다이렉션이 왜 쉘의 기능인지,
echo 가 왜 환경마다 다르게 느껴지는지까지 한 번에 연결된다.