자주 사용하는 옵션
ps -ef
: process들의 상태를 확인.
→ 형식: UID PID PPID C STIME TTY TIME CMD
ps aux
: process들의 상태를 cpu, memory 사용률과 함께 확인.
→ 형식: USER PID %CPU %MEM VSZ RSS TT STAT STARTED TIME COMMAND
파이프 후 grep 으로 원하는 프로세스만 볼 수 있다.
→ ps aux | grep java
실행하면 java 라는 단어를 명령어나 파라미터로 넣은 프로세스를 확인
내가 전혀 모르는 서버에 들어가서도 ps 명령어 사용하고 내가 띄운 어플리케이션이 잘 돌고 있나? 아니면 어플리케이션 로그나 이런 걸로 확인할 수 없는 다른 정보들을 확인할 때, 프로세스 레벨에서 확인할 때 이 명령어 사용한다.
PID
: 프로세스 ID
PPID
: parent PID (프로세스는 결국 parent 프로레스가 시작을 해줘야 실행될 수 있다.)
그래서 parent child 구조로 되어 있는데 커널이 시작될 때 가장 먼저 실행된 프로세스들이 0번을 parent로 가지고 나머지는 다 앞에 있는 다른 프로세스 id를 parent id 로 가진다.
C
: 짧은 기간 동안의 CPU 사용율(C:Sys V, CP :BSD)
STIME
: start time 같구요
TTY
: 이 프로세스가 실행되어 있는 session, 지금 터미널에 접속해 있는 이걸 session이라고 하는데 물음표는 없다는 뜻이다.
컴퓨터가 실행될 때는 자동으로 외부에서 실행을 하니까 그 때 커널이 시작되면 자동으로 시작된 것들은 누가 사람이 터미널에 접속해서 실행시킨 게 아니라 자동으로 커널이 실행되면서 이 프로세스들이 뜨드록 설계가 된 거기 떄문에 물음표로 되어 있을 것. Ubuntu bash 같은 경우 pts0라고 되어 있는데 Mac에서는 ttys000 이런 식으로 되어 있다.
TIME
: 총 CPU 사용 시간
CMD
: 이거 실행할 때 사용한 명령어가 어떤 명령어를 사용했냐 라는 걸 의미
sleep 1000 &
이렇게 치면
[1] 23606
PID 나옴
ps -ef | grep sleep
이렇게 grep으로 아까 실행시킨 sleep 을 검색하면
이런 결과 나오고
501 23606 15591 0 2:39AM ttys003 0:00.00 sleep 1000
ef의 옵션에서 아까 봤던 PID 23606 고
그리고 그 친구의 patent process ID 는 15591다 ~
process 에 signal 을 전달합니다.
아래 명령어에서 숫자 또는 괄호안의 글자 중 한가지 사용.
kill - 9(SIGKILL) $pid
프로세스를 강제로 종료합니다.
kill -15(SIGTERM) $pid EE kill $pid
종료하겠다는 Signal을 보낸다. 이 Signal을 처리하는 코드를 짤 수도, 무시 할 수도, 막을 수도 있다.
kill 명령어의 15번 시그널(SIGTERM)은 일반적인 터미널 환경에서는 자주 활용되지 않지만, 컨테이너 환경(Kubernetes 등)에서 어플리케이션을 제어할 때 가장 많이 사용하는 시그널 중 하나다.
SIGTERM(15번 시그널)은 프로세스에 종료 요청을 보내는 시그널이고, 어플리케이션이 이 시그널을 처리하는 코드가 포함되어 있다면, 해당 코드를 실행한 후 종료할 수 있다. 따라서, 어플리케이션 개발자로서 리눅스 환경에서 실행되는 프로그램을 개발한다면, SIGTERM을 수신했을 때 어플리케이션이 사용했던 데이터를 안전하게 정리하고 종료하는 로직을 직접 정의할 수 있다. 이를 통해 데이터 유실을 방지하고, 안전한 종료 절차를 구현할 수 있다.
예시) 데이터베이스에 네트워크로 연결하여 데이터를 쓰고 있는 상황을 가정해 보자. 그런데 중간에 누군가 kill 신호를 보내서 프로세스를 종료시키면, 예를 들어 100개의 요청 중 10개만 전송된 상태에서 프로세스가 종료될 수 있다. 이 경우, 나머지 90개의 요청이 정상적으로 처리되지 않았음을 운영자나 개발자가 알아야 한다. 그래야만 해당 부분을 복구하거나 적절한 대처를 할 수 있다.
만약 kill -9 명령어를 사용하여 강제 종료해 버리면, 프로세스가 종료되기 전에 이를 처리할 기회조차 없이 즉시 사라지게 된다. 그러나 일반적으로 여러 대의 서버를 자동화된 도구로 운영하는 환경에서는 먼저 SIGTERM(시그텀) 신호를 보내 프로세스가 정상적으로 종료될 시간을 주는 것이 정석적인 방법이다. 이렇게 하면 프로세스가 진행 중이던 작업을 마무리하고 종료될 수 있다. 이후에도 종료되지 않으면 최후의 수단으로 kill -9을 사용하는 것이 바람직하다
많이 사용하는 스프링 같은 서버 프레임워크나 데이터베이스 시스템 등, 안정성이 중요한 프로그램들은 대부분 SIGTERM 신호를 처리하는 로직을 기본적으로 포함하고 있다. 즉, 이런 프로그램들은 SIGTERM을 받으면 단순히 즉시 종료되는 것이 아니라, 현재 진행 중인 작업을 정리한 후 안전하게 종료되도록 설계되어 있다.
우리가 직접 신경 쓰지 않아도, 이러한 로직이 백그라운드에서 자동으로 동작하고 있다고 이해하면 된다.
kill -2(SIGINT) $pid
interrupt 를 의미하는 signal. process를 유지하고 있는 session에서 ctrl+c 를 누르면 이 signal이 전달된다.
-> 대화형 스크립트에서 ctrl+D 를 누르면 세션 종료가 가능한 것은 EOF(end-of-file)을 의미한다. ctrl+D는 signal이 아니다.
socket status 의 약어
내가 어플리케이션을 띄웠는데 이게 제대로 떴나? 아니면 내가 어플리케이션을 띄웠는데 (우리가 주로 웹서비스 형태 어플리케이션 띄우니까) 이게 안 떴는데 내가 점유하려는 호스트 번호가 이미 사용 중이어서 이런 에러가 나면서 뜨지 않는 경우를 종종 맞이할 수 있다.
어떤 프로세스가 내 포트를 사용하고 있지? 이런 걸 확인할 때 사용하기도 함.
그리고 어플리케이션이 정상 종료되었는지, 안 종료됐는지 이런 것도 소켓이 열렸는지 닫혔는지 통해서 간접적으로 확인할 때도 있다.
사용 옵션
SS
: 연결이 맺어진 (STATUS=ESTAB) 소켓 확인 -a
: 열려있는 모든 소켓-|
: listening 중인 소켓만 표시-t
: TCP socket 확인, 필요에 따라 -l, -a 등과 함께 사용-u
: UDP socket 확인, 연결을 맺지 않는 UDP 특성상 항상 -a -l 등과 함께 사용MacOS에서는 ss 명령어가 기본적으로 제공되지 않는다.
ss(Socket Statistics) 명령어는 Linux 기반 시스템에서 소켓 연결 상태를 확인하는 도구이며, MacOS의 BSD 기반 네트워크 스택에는 포함되지 않는다.
MacOS에서 ss 명령어 대체 방법
1. netstat 사용 (기본 제공됨)
2. lsof 사용 (포트 점유 프로세스 확인)
3. nmap 사용 (추가 설치 필요)
4. tcpdump 사용 (실시간 트래픽 확인)
ss-a
UNCONN : 커넥션 맺어지지 않았다.
LISTEN : 포트가 열려 있어서 어떤 요청이 오면 그걸 가지고 뭔가를 할 수 있는 상태.
ss 하고 내 서비스가 지금 동작하고 있어 라는 걸, 내가 포트를 열고 외부의 요청을 받아주는 서버를 만들었을 때, 우리가 앞으로 데이터 엔지니어에서 배우게 될 대부분의 어플리케이션은 서버형 어플리케이션일 텐데, 포트를 무언가 항상 하나라도 열고 있을 것이다. 그러면 이 친구가 제대로 떠서 요청을 받을 준비가 됐어. 라는 걸 볼 때, 그러면 Listen 상태의 어플리케이션을 확인하게 된다.
ss -l
이렇게 하면 현재 Listening 중인 프로세스들이 쭉 표시됨.
ss -t
모든 소켓이 나와 있는데 우리가 운영하는 어플리케이션 대부분 TCP 연결 기반의 HTTP를 많이 쓸 텐데 TCP만 확인할 일이 많다. 이렇게 TCP 소켓만 확인 가능하다. (UDP는 -u)
ss -s
현잿 소켓 상태의 통계를 볼 수 있다.
total n개 중에 TCP n개다. TCP n 개중에 연결이 된 건 n개다. 연결된 것 나머지는 Listen 중이겠죠. 나머지가 0이 되어 있으니까. 그리고 프로토콜 중에는 UDP가 몇개 , TCP가 몇개, INET(인터넷 네트워크) 있고 FRAG (프레그먼트 레이어) 이거는 이 밑에 있는 INET이랑 FRAG라는 표시는 OSI7 Layer 중 2계층과 3계층을 의미한다.
ss -e
Extended Output 이라고 해서 위에 보다 더 많은 정보가 나오고, 화살표 표시로 받는 요청을 하는 건지, 양방향인지 표시됨.
ss -m
네트워크 사용량을 같이 표시를 해 줌. 사용량 표시하는 방법은 skmem 이라고 리눅스에서 표시하는 형식이 있는데 이 형식에 맞게 사용을 함 이 skmem이 실제로 어떤 형식으로 이루어져 있는지 실제로 외워서 하는 건 아니고 인터넷 검색해서 그 때 그 때 내가 띄운 어플리케이션이 네트워크를 이 포르토 열고 있고 메모리 사용률은 아 이렇게 사용하고 있구나 이런걸 순간적으로 확인할 때 사용.
ss는 앞으로 내가 열고 있는 포트, 내가 띄운 어플리케이션이 네트워크 관련된 문제로 뜨지 않아. 이럴 때, 혹시 자주 발생하는 게 내가 미리 띄워놨는데 그걸 까먹고 다시 실행하려고 했을 때 그런 경우가 발생한다던지, 아니면 앞에서 어플리케이션이 비정상적으로 종료가 됐는데 그 때 네트워크 포트가 정리가 안 돼서 운영체제에서 일정 시간 그 포트를 강제로 종료하지 않아 포트의 점유가 발생한 경우, 이렇게 ss 명령어로 그런 포트가 있는지 확인하고 어떤 프로세스가 이 포트를 사용하고 있는 지 확인할 때 사용.
history | grep "find"
history 명령어는 일반적으로 터미널 세션이 유지되는 동안만 기록을 확인할 수 있다. 하지만 MacOS에서 여러 가지 플러그인을 설치해 사용하는 경우, 컴퓨터를 껐다 켜도 이전 명령어 기록이 남아 있는 경우가 있다.
이러한 차이는 명령어 기록이 파일로 저장되는지 여부 때문이다.
Zsh을 사용하는 경우: 홈 디렉터리(/~)에 .zsh_history 파일이 존재하면, 터미널을 재시작해도 이전 기록을 불러올 수 있다.
Bash를 사용하는 경우: .bash_history 파일이 기록을 저장하며, 일부 플러그인을 사용하면 자동으로 히스토리를 불러오는 기능이 추가될 수도 있다.
즉, 히스토리가 유지되는 이유는 이전 명령어 기록이 특정 파일(.zsh_history, .bash_history 등)에 저장되기 때문이며, 터미널이 시작될 때 이 파일에서 기록을 불러와 history 명령어로 확인할 수 있게 되는 것이다.
기본적으로 모든 서버에 해당 플러그인 같은 기능들이 제공된다고 볼 수는 없다.
!1991
history에서 확인한 명령어 숫자를 이런 식으로 불러올 수 있다.
출력 결과를 파일로 저장
>
: 기존의 파일 내용을 지우고 저장
>>
: 기존 파일 내용 뒤에 저장
<
: 파일의 데이터를 명령어에 입력
<<
: 지정한 단어까지의 데이터를 명령어에 입력
echo "1st" > lines
cat lines
1st
echo '2nd' > lines
cat lines
2nd
앞에 first라는 단어가 있었던 lines 파일에 있던 건 찾을 수 없고 두 번째에 있던 second 라는 단어만 있는 것을 볼 수 있다. 실제로 그 파일에 어떤 게 있던지 그냥 새로 이 파일을 써버리는 것을 recdirection 표현이 한다고 이해하면 됨.
그러면 원래 파일 바꾸지 않고 새로 추가만 하고 싶다면? 꺽쇄를 두 개 표시해준다.
echo '3rd' >> lines
cat lines
출력 :
2nd
3rd
wc -l lines
출력 :
2 lines
각 file의 newline, word, byte counts를 print 한다.
옵션
-l
: 라인 수 count 해줘.
wc -l 에서 나는 파일 이름이 또 뜨는 게 싫어. 그래서 얘한테 순수하게 input만 줄 거야. 이럴 때 왼쪽 꺽쇄 lines 하면 이 표현 자체가 이 앞에 있는 wc랑 상관 없이 이 파일에 있는 내용을 출력해서 앞에 명령어에다 넣어줘 라는 거고
wc -l < lines
이렇게 하면 2 순수하게 line 수만 카운트 해서 결과나 나온 것을 볼 수 있다.
그 다음에 이 왼쪽 화살표를 한 번 하는 게 아니라 두 번 하면 내가 여기다가 지정한 단어가 나올 때 까지 입력을 해줘 라는 명령어가 된다.
wc -l << EOF
heredoc> 1st
heredoc> 2nd
heredoc> 3rd
heredoc> EOF
출력 : 3
EOF 가 올 때 까지 입력 왼쪽에 있는 명령어에(wc -l)입력을 넣어 줄거야. 라는 의미가 있다는 걸 볼 수 있다.
wc -l << END
heredoc> This is the END
heredoc> END
실제 단어가 어느 줄에 어떤 콤비네이션과 상관 없이 입력되는 것이 아닌 순수하게 종료 단어만 입력해야 개행으로 입력돼야 앞에 있는 명령어의 파라미터로 이전에 입력된 것들을 보내준다는 것을 알 수 있다.
모든 프로세스는 표준 입력(입력 데이터)과 표준 출력(출력 데이터)을 담당하는 표준 입출력(standard I/O, stdin/stdout/stderr)을 가진다. 리눅스에서는 프로세스의 표준 입출력을 제어하여 원하는 방식으로 출력 결과를 저장하거나 처리할 수 있다.
1>
: stdout(표준 출력)을 지정된 파일에 저장
2>
: stderror(표준 에러)를 지정된 파일에 저장
2>&1
또는 &>
: stderror 를 stdout에 포함시켜서 저장
>/dev/null
: 출력 결과를 제거
리눅스에서 명령어 실행과 표준 출력, 표준 에러의 동작
리눅스에서 터미널에 명령어를 입력하면, Bash Shell이 해당 명령어를 실행하는 프로세스를 생성하고 그 결과를 출력한다. 실제로 터미널에서 이렇게 명령 하나를 입력해서 그 결과가 바로바로 나오는 것들을 봤을 텐데, 실제 그 잠깐의 순간에 리눅스가 이 bash shell에 입력한 것에 대해서 프로세스를 실행했다가 실행되고 끝난 결과를 보여주는 것이다. 실행 도중 결과도 물론 볼 수 있다.
출력과 에러를 각각 저장하는 예제
find . -name "my*" 1> ./stdout.log 2> ./stderror.log
find . -name "my*"
: 현재 디렉토리(.)에서 "my"로 시작하는 파일을 찾는 명령어
1> ./stdout.log
: 찾은 파일 목록(stdout)을 stdout.log 파일에 저장
2> ./stderror.log
: 권한 문제 등으로 인해 발생한 오류(stderr)를 stderror.log 파일에 저장
find 해서 나온 결과 를 stdout에 어떤 디렉토리를 찾았는지 저장된 것을 볼 수 있고,
그 안에 permission denied됐다는 것은 우리가 색깔로 하이라이팅 되진 않았지만 실제로 명령어를 수행하다가 중간에 에러가 난 경우나 예상 외 결과가 나타난 경우다. 이런 경우 아하~ stderror 로 뽑아주는 결과구나 해서 1과 2의 redirection 표시로 다른 파일을 저장할 수있는 것을 알 수 있다.
터미널에서 실행했을 때 화면에서 빨간색으로 표시되는 Permission denied 같은 메시지는 사실 stderr(표준 에러)로 출력되는 것이며, 이를 2>를 이용해 별도로 저장할 수 있다.
이처럼 stdout과 stderr을 분리하여 저장하면, 정상적인 출력과 오류 메시지를 각각 관리할 수 있어 디버깅과 로그 분석이 더 쉬워진다.
이건 꼭 find 명령어 뿐만 아니라 우리가 실행하는 어플리케이션과 마찬가지다. 서버를 운영해보신 분들 중에 로거라는 것들을 써보신 분들 중에 로거 인포 아니면 로거 에러 이렇게 로그 레벨을 나눠서 로그를 남겨본 경험이 있는 분들이 있을 텐데 그냥 로그 남겨놓으면 로프 파일 남는 거 아니야? 라고 생각할 수도 있지만 실제로는 로그 에러 같은 경우 표준 출력에서 stderror로 표시가 된다.
어? 그러면 저는 하나의 파일에서 std 정상 출력 결과랑 에러를 같이 봤는데요? 라고 하신 분들이 있을 수도 있는데 그런 분들은 실제로 그 어플리케이션에서 우리가 모르는 곳에서 표준 에러를 표준 출력에 붙여서 표현을 해준 경우가 그렇게 될 거다.
find . -name "my*" 1> ./stdout.log 2> ./stderror.log
vi stderror.log
vi stdout.log
두 파일 합치면 아래 처럼 됨.
find . -name "my*" 1> ./both.log 2>&1
vi both.log
위에 코드를 축약한 게 아래 & 사용한 아래 코드.
find . -name "my*" &> ./both_simple.log
diff both.log both_simple.log
두 파일이 같아서 출력 없음.
이런 경우도 있을 수 있다.
나는 표준 출력은 관심 있는데 표준 에러는 안 볼래. 또는 표준 출력은 내용이 너무 나오니까 나는 에러만 볼래. 이런 경우에는
find . -name "my*" 1> ~/stdout2.log 2> /dev/null
/dev/null
: 파일 지정 안 해줬으니까 무효표시할거야 라는 의미.