grep 명령은 거짓 긍정 결과를 제공합니다

grep 명령은 거짓 긍정 결과를 제공합니다

이 명령을 사용하여 (루프에서) 특정 이름으로 실행 중인 모든 프로세스의 수를 얻은 다음 추가로 수를 결정하지만 때로는 모든 프로세스에 대해 잘못된 답변을 제공하고 때로는 동일한 루프의 일부 프로세스에 대해 잘못된 답변을 제공합니다. 일부 서버에서는 전혀 문제가 없습니다. 수동으로 확인해 보니 잘못된 것으로 나타났습니다.

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. 또는 가 아닌 다른 매개변수와 일치할 수도 있습니다.chazelasargv[0]
  • grep | wc -lgrep -c.

여기에는 이름(또는 기타 중요한 기준)으로 프로세스를 일치시키는 (비표준이지만 매우 일반적인) 명령이 있습니다.pgrep

pgrep -xc -- "$1"

c어떤 프로세스가 계산 되나요?이름ps(without에서 보고한 대로 -f) e x는 의 정규식과 정확히 일치합니다 $1. 프로세스 이름 대신 전체 인수 목록( 에서 보고한 대로)을 일치시키려면 -f, 를 사용하십시오 .pgrepps -f

이로 인해 정규식 연산자가 포함된 프로세스 이름 문제가 발생합니다(위에서 언급한 대로 .). 불행히도 정규식 일치 대신 문자열 비교를 수행하는 옵션이 pgrep없으므로 정규식 연산자를 이스케이프 처리해야 합니다.-F

또 다른 옵션은 ps보고할 프로세스 이름만 지정한 다음 이를 사용하여 고정 문자열 비교를 grep -xF수행하는 것입니다 .xF

ps -Ao comm= | grep -Fxce "$1"

프로세스 이름 대신 인수 목록(잘릴 수 있지만 일부 구현에서는 하나 이상의 인수가 줄 길이 제한을 늘릴 수 있음 )을 인쇄하는 comm것으로 대체되었습니다 .argsps-w

어떤 경우든 모든 사용자는 모든 이름과 매개변수 목록을 사용하여 프로세스를 만들 수 있으므로 이름으로 프로세스를 찾는 것은 매우 취약합니다. 누구나 동일한 이름과 동일한 매개변수 목록으로 프로세스를 시작하여 완전히 다른 명령을 실행함으로써 프로세스가 거기에 있다고 생각하도록 속일 수 있습니다.

일반적으로 프로세스에서 제공하는 서비스의 가용성을 확인하거나 현재 사용 중인 일부 리소스를 예약하는 것이 좋습니다.

-u경우에 따라 유효한 uid( in pgrep) 또는 현재 실행 중인 실행 파일의 경로와 같은 추가 기준을 검색에 추가할 수 있습니다 .

Linux에서는 다음을 사용하십시오 zsh.

pids=(/proc/<->(Nnu[chazelas]e['[[ $REPLY/exe -ef /usr/bin/sleep ]]']:t]))

$pids예를 들어 사용자는 코드를 실행하는 프로세스의 ID로 파일에 저장되며 이를 사용하여 목록이 비어 있지 않은지 확인할 수 있습니다. (검색에서 명령을 또는로 바꾸십시오)./usr/bin/sleepchazelasif (($#pids > 0)); then.../usr/bin/sleep=sleep$commands[sleep]sleep$PATH

보다 일반적으로는 서비스 관리자에게 의존하여 서비스와 프로세스를 관리하는 것이 가장 좋습니다. 이와 같은 현대적인 장치는 systemd이를 안정적으로 수행할 수 있는 시설을 제공할 것입니다.

답변2

  1. 어떤 경우에는 이상한 타이밍 효과가 발생할 수 있습니다.
  2. 찾고 있는 내용에 따라 다른 일치 항목이 있을 수도 있습니다. 그렇지 않은 경우 wc확인 방법으로 인해 일치하는 항목이 두 개 있으면 실행되지 않았다고 보고합니다. (즉, -ge대신 사용하는 것을 고려하십시오 -eq.)
  3. 보다 효율적인 테스트는 을 사용하는 것입니다 killall -0 commandname. 신호 0으로 종료하면 실제 신호가 전송되지 않지만 아무것도 발견되지 않은 경우 오류 표시를 포함하여 모든 오류 검사가 수행됩니다. (한 가지 단점: 루트가 아닌 이상 자신의 프로세스가 아닌 프로세스를 종료하는 것도 오류입니다. 이 --user옵션이 도움이 될 수 있습니다.)

관련 정보