Calibre-Web 의 rc.d 스크립트를 작성하면서, 내가 사용하는 jupyter-lab 의 rc.d 스크립트가 뭔가 좀 이상하다는 생각이 들었다. 그래서 다시 확인해 봤는데, 역시나… 프로세스 ID 를 제대로 골라내질 못하고 있었다.
처음에는 user 와 command 변수에 지정한 명령으로 pid 를 찾았다. 각각 -u 옵션과 -f 옵션이다.
pgrep -u "${user}" -f "${command}"
저렇게 하면 하나만 나왔고, Jail 의 shell 에 들어가서 service status 를 확인해도 하나만 나와서 잘 되는 줄 알았는데…
shell > service jupyter status
jupyter running with pid: 97074
시간이 좀 지난 다음에 검색하면 왜인지는 모르겠는데, root 에서 실행한 su 명령이 user 계정에서 실행한 것 처럼 바뀌어서 저 조건으로 2개가 나온다.
shell > pgrep -l -u jupyter -f jupyter-lab
97070 _su -c /usr/local/bin/jupyter-lab
97074 /usr/local/bin/python3.9 /usr/local/bin/jupyter-lab
그래서 su 명령으로 실행한 프로세스를 종료하면 될거라 생각했는데, python 으로 실행한 jupyter-lab 은 딱 해당하는 pid 로 kill 명령을 넣지 않으면 제대로 프로세스가 종료되지 않았다. 그래서 ${command} 대신 “python3” 로 검색했는데, 아까멩키로 처음에는 한 개만 잘 나오다가 시간이 좀 지나면…
shell > service jupyter status
jupyter running with pid: 97245
97246
97255
97074
이렇게 여러 개 나온다. -l 옵션을 넣어서 어떤 놈들인가 찾아봤다.
shell > pgrep -l -u jupyter -f python3
97245 /usr/local/bin/python3.9 -m ipykernel_launcher -f /usr/home/jupyter/.local/share/jupyter/runtime/kernel-09dfa3c9-f584-41ef-bcd5-526bacda24a6.json
97246 /usr/local/bin/python3.9 -m ipykernel_launcher -f /usr/home/jupyter/.local/share/jupyter/runtime/kernel-d28efcc1-7365-4a5c-99d5-a372bfd0896c.json
97255 /usr/local/bin/python3.9 -m pylsp
97074 /usr/local/bin/python3.9 /usr/local/bin/jupyter-lab
음… su 는 제대로 필터링이 되었는데, 내가 작업공간에 생성한 두 개의 가상 커널과 파이썬 랭귀지 서버 프로토콜이 추가로 나온다. man pgrep 를 뒤져서 일단 찾은 해결책은 -o 옵션을 사용하여 검색 된 것 중 가장 오래된 프로세스의 pid 를 구하는 것이지만, 내 생각엔 -f 옵션에서 and 나 or 로 검색조건을 설정할 수 있으면 더 확실하겠다 싶었다. 그래서 그냥 짬으로 & 를 넣어 봤는데… 안된다. or 조건은 빈칸 혹은 | 으로 되는데 & 는 도당췌 되질 않는다.
그래서 ChatGPT 한테 물어봤는데, 이 녀석은 이런 답을 줬다.
pgrep -lf 'string 1' | grep 'string 2' | awk '{print $1}'
그러니까 python3 로 검색해서 1차로 리스트를 뽑고, 그걸 grep 을 사용하여 jupyter-lab 으로 거른 다음, awk 로 맨 앞의 pid 만 뽑아내라는 거였다. 처음 이 답을 얻었을 때 우와~ 하면서 rc.d 스크립트에 넣어봤는데, 마지막의 $1 을 rc.d 스크립트가 변수로 취급해서 자꾸 에러가 났다. 하… 더 캐물어볼까 하다가 그냥 적당히 검색을 했는데…
드디어 걸려 나왔다.
> pgrep -f "otp.*place1"
뜬금없게도 .* 이 and 조건을 거는 구분자라고 한다.
정확하게는 정규식 표현이다. ’.‘ 은 두 string 사이에 어떤 글자가 들어와도 된다는 거고, ’*‘ 은 그 글자에 길이제한을 두지 않는다는 의미다. 그러니 순서를 반대로 하면 검색이 안 된다. 따져보면 and 조건이랑은 의미가 좀 다르다. -f 옵션에 정규식이 된다고 man 페이지에서 봐 놓고는 그냥 and 만 찾아 헤멨다. 미친… ㅋㅋㅋ
여튼 실행해보면…
shell > pgrep -u jupyter -f "python3.*jupyter-lab"
97074
하나만 걸려 나온다.
이제서야 가상 커널을 여러 개 열어도 service stop, status, restart 가 제대로 동작한다. 후… 나중에 다시 삽질하지 말라고 수정한 Jupyter 의 rc.d 스크립트를 적어둔다. 내가 참고한 원본은 /var/run/ 폴더에 pid 파일을 생성해서 그걸로 pid 를 가져오는 식이었는데, 아무리 해도 pid 파일이 제대로 생성되지 않았다. 그래서 이 삽질을…T^T
#!/bin/sh
#
# PROVIDE: jupyter
# REQUIRE: LOGIN
#
# Add the following lines to /etc/rc.conf to enable jupyter notebook server
#
#
# jupyter_enable (bool): Set to "NO" by default,
# Set it to "YES" to enable jupyter notebook server
. /etc/rc.subr
name=jupyter
command=/usr/local/bin/jupyter-lab
rcvar=jupyter_enable
load_rc_config $name
jupyter_enable="${jupyter_enable-"NO"}"
jupyter_user="${jupyter_user-"jupyter"}"
export HOME=/home/jupyter
start_cmd="su ${jupyter_user} -c '${command}' &"
stop_cmd="${name}_stop"
status_cmd="${name}_status"
jupyter_stop()
{
jupyter_pid=$(pgrep -u "${jupyter_user}" -f python3.*"${command}")
echo "Stopping ${name}."
kill -s TERM "${jupyter_pid}"
}
jupyter_status()python3.*"${command}"
{
jupyter_pid=$(pgrep -u "${jupyter_user}" -f python3.*"${command}")
if [ -n "${jupyter_pid}" ]
then
echo "${name} running with pid: $jupyter_pid"
else
echo "${name} not running? (pid not found)"
fi
}
command_args=" >/dev/null 2>&1 &"
load_rc_config $name
run_rc_command "$1"
–참고 사이트–
https://serverfault.com/questions/985824/pgrep-search-multiple-words
https://stackoverflow.com/questions/58527655/pgrep-multiple-process-names