원격 서버의 프로세스를 정리하려고 ssh my-server 'pkill -f 패턴' 을 실행하면 뒤에 이어 붙인 명령이 실행되지 않고 연결이 끊긴다. pkill 이 자기 자신을 실행한 셸까지 죽이기 때문이다.
증상
ssh my-server 'pkill -f my-worker; sleep 1; systemctl --user start my-worker'
워커는 죽는데 뒤의 start 가 실행되지 않는다. ssh 는 종료 코드 255 나 시그널로 끝난 것으로 돌아온다. 서버에 직접 로그인해서 같은 pkill 을 치면 아무 문제가 없어서 더 헷갈린다.
원인
-f 옵션은 프로세스 이름이 아니라 전체 명령줄에서 패턴을 찾는다. 그런데 ssh 로 명령을 넘기면 서버 쪽에서는 이런 프로세스가 생긴다.
bash -c pkill -f my-worker; sleep 1; systemctl --user start my-worker
이 셸의 명령줄에도 my-worker 라는 글자가 들어 있다. pkill 은 자기 자신은 제외하지만 부모 셸은 제외하지 않으므로, 워커와 함께 이 셸도 죽인다. 셸이 죽으니 뒤의 명령은 실행될 기회가 없다.
해결
- 전체 일치로 좁힌다.
-x를 같이 주면 명령줄 전체가 패턴과 정확히 일치하는 프로세스만 대상이 된다.ssh my-server 'pkill -x -f "node /srv/app/worker.js"' - pid 로 죽인다. pid 파일이나
systemctl show -p MainPID로 번호를 얻어서kill한다. - 서비스 관리자에 맡긴다. systemd 유닛이라면
systemctl restart가 가장 깔끔하다. - 자기 자신과 일치하지 않게 패턴을 쓰는 요령(
pkill -f '[m]y-worker')도 있다. 대괄호 때문에 셸 명령줄의 글자와는 일치하지 않고, 실제 프로세스와는 일치한다.
정리
pkill -f 는 "이 글자가 명령줄 어딘가에 있는 모든 프로세스"를 죽인다. 원격으로 한 줄에 실어 보내면 그 한 줄 자체가 대상이 된다. 자동화 스크립트에서는 -x -f 나 pid 를 쓰는 것을 기본으로 삼자.
댓글 없음:
댓글 쓰기