이 명령을 사용하여 (루프에서) 특정 이름으로 실행 중인 모든 프로세스의 수를 얻은 다음 추가로 수를 결정하지만 때로는 모든 프로세스에 대해 잘못된 답변을 제공하고 때로는 동일한 루프의 일부 프로세스에 대해 잘못된 답변을 제공합니다. 일부 서버에서는 전혀 문제가 없습니다. 수동으로 확인해 보니 잘못된 것으로 나타났습니다.
check_process() {
process_count=$(ps -eaf | grep -v grep | grep "$1" | wc -l)
if [ "${process_count}" -eq 1 ]; then
PROCESS_EXISTS=0
echo $1 " is running"
else
PROCESS_EXISTS=1
echo $1 " is not running"
fi
}
또한 문제가 발생하기 시작한 지난 2~3개월 전까지는 거의 2년 동안 훌륭하게 작동했었다는 점도 언급하고 싶습니다.
답변1
ps -f
다음과 같은 출력을 제공합니다.
chazelas 11042 10528 1 08:49 ? 00:00:03 /usr/lib/firefox/firefox -contentproc -childID 6 -isForBrowser -prefsLen 7847 -prefMapSize 699608 -parentBuildID 20200720193547 -appdir /usr/lib/firefox/browser 10528 true tab
grep "$1"
많은 계정에서 프로세스 이름이 지정된 행을 반환하는 것은 오류입니다.
$1
로 시작하면 실패합니다-
.grep -e "$1"
또는 가 필요합니다grep -- "$1"
. 임의의 데이터를 명령에 전달할 때 옵션 끝 구분 기호를 사용하는 습관을 들여야 합니다.grep
일치를 위해 정규식 패턴을 사용합니다(예re
:grep
). 예를 들어grep a.py
일치합니다. 를 사용하여 하위 문자열을 검색aspy
할 수 있습니다 .grep -F
ps -f
보고 프로세스 없음이름하지만 그 과정은논쟁(argv[0]
일반적으로 관례에 따라 명령인 경로 포함)- 일치하는 줄 내에서 위치를 제한하지 않고 정규식/하위 문자열을 찾고 있습니다. 예를 들어 위의
$1
==는 에서as
일치합니다as
. 또는 가 아닌 다른 매개변수와 일치할 수도 있습니다.chazelas
argv[0]
grep | wc -l
예grep -c
.
여기에는 이름(또는 기타 중요한 기준)으로 프로세스를 일치시키는 (비표준이지만 매우 일반적인) 명령이 있습니다.pgrep
pgrep -xc -- "$1"
c
어떤 프로세스가 계산 되나요?이름ps
(without에서 보고한 대로 -f
) e x
는 의 정규식과 정확히 일치합니다 $1
. 프로세스 이름 대신 전체 인수 목록( 에서 보고한 대로)을 일치시키려면 -f
, 를 사용하십시오 .pgrep
ps -f
이로 인해 정규식 연산자가 포함된 프로세스 이름 문제가 발생합니다(위에서 언급한 대로 .
). 불행히도 정규식 일치 대신 문자열 비교를 수행하는 옵션이 pgrep
없으므로 정규식 연산자를 이스케이프 처리해야 합니다.-F
또 다른 옵션은 ps
보고할 프로세스 이름만 지정한 다음 이를 사용하여 고정 문자열 비교를 grep -xF
수행하는 것입니다 .x
F
ps -Ao comm= | grep -Fxce "$1"
프로세스 이름 대신 인수 목록(잘릴 수 있지만 일부 구현에서는 하나 이상의 인수가 줄 길이 제한을 늘릴 수 있음 )을 인쇄하는 comm
것으로 대체되었습니다 .args
ps
-w
어떤 경우든 모든 사용자는 모든 이름과 매개변수 목록을 사용하여 프로세스를 만들 수 있으므로 이름으로 프로세스를 찾는 것은 매우 취약합니다. 누구나 동일한 이름과 동일한 매개변수 목록으로 프로세스를 시작하여 완전히 다른 명령을 실행함으로써 프로세스가 거기에 있다고 생각하도록 속일 수 있습니다.
일반적으로 프로세스에서 제공하는 서비스의 가용성을 확인하거나 현재 사용 중인 일부 리소스를 예약하는 것이 좋습니다.
-u
경우에 따라 유효한 uid( in pgrep
) 또는 현재 실행 중인 실행 파일의 경로와 같은 추가 기준을 검색에 추가할 수 있습니다 .
Linux에서는 다음을 사용하십시오 zsh
.
pids=(/proc/<->(Nnu[chazelas]e['[[ $REPLY/exe -ef /usr/bin/sleep ]]']:t]))
$pids
예를 들어 사용자는 코드를 실행하는 프로세스의 ID로 파일에 저장되며 이를 사용하여 목록이 비어 있지 않은지 확인할 수 있습니다. (검색에서 명령을 또는로 바꾸십시오)./usr/bin/sleep
chazelas
if (($#pids > 0)); then...
/usr/bin/sleep
=sleep
$commands[sleep]
sleep
$PATH
보다 일반적으로는 서비스 관리자에게 의존하여 서비스와 프로세스를 관리하는 것이 가장 좋습니다. 이와 같은 현대적인 장치는 systemd
이를 안정적으로 수행할 수 있는 시설을 제공할 것입니다.
답변2
- 어떤 경우에는 이상한 타이밍 효과가 발생할 수 있습니다.
- 찾고 있는 내용에 따라 다른 일치 항목이 있을 수도 있습니다. 그렇지 않은 경우
wc
확인 방법으로 인해 일치하는 항목이 두 개 있으면 실행되지 않았다고 보고합니다. (즉,-ge
대신 사용하는 것을 고려하십시오-eq
.) - 보다 효율적인 테스트는 을 사용하는 것입니다
killall -0 commandname
. 신호 0으로 종료하면 실제 신호가 전송되지 않지만 아무것도 발견되지 않은 경우 오류 표시를 포함하여 모든 오류 검사가 수행됩니다. (한 가지 단점: 루트가 아닌 이상 자신의 프로세스가 아닌 프로세스를 종료하는 것도 오류입니다. 이--user
옵션이 도움이 될 수 있습니다.)