우리 시스템은 종종 ps -C cmdName
프로세스가 실행 중인지 확인하고 그렇지 않은 경우 다시 시작하는 데 사용됩니다.
Centos 6에서 Centos 8로 마이그레이션할 때 동작에 변화가 있는 것 같았는데 ps -C
, 이로 인해 시스템이 많이 손상되었습니다.
센토스 6(32비트)
예, 프로세스가 있습니다.
# ps aux | grep DvBuildSegmentList
root 16223 4.0 0.1 16064 11272 pts/0 S 14:14 0:00 ./DvBuildSegmentList
root 16264 0.0 0.0 4416 1880 pts/0 S+ 14:14 0:00 grep DvBuildSegmentList
그리고 ps -C
전체 명령 이름에서 프로세스를 감지합니다.
# ps -C DvBuildSegmentList
PID TTY TIME CMD
16223 pts/0 00:00:00 DvBuildSegmentL
(출력에서 잘린 명령줄에 유의하세요)
센토스 8(64비트)
예, 프로세스가 있습니다.
# ps aux | grep DvBuildSeg
root 15282 0.9 0.2 99796 42424 pts/1 S 14:18 0:04 ./DvBuildSegmentList
root 16989 0.0 0.0 221900 1104 pts/1 S+ 14:26 0:00 grep --color=auto DvBuildSeg
전체 명령 이름을 사용하는 출력은 없습니다.
# /bin/ps -C DvBuildSegmentList
PID TTY TIME CMD
그러나 단축된 명령 이름을 사용하면 프로세스가 감지됩니다.
# /bin/ps -C DvBuildSegmentL
PID TTY TIME CMD
15282 pts/1 00:00:06 DvBuildSegmentL
32비트 Centos 6과 64비트 Centos 8을 모두 유지해야 하며 많은 코드를 다시 작성하지 않는 것이 가장 좋습니다.
ps
버전 간에 동일한 동작을 얻을 수 있는 방법이 있습니까 ? (명령 이름은 이름 충돌로 인해 처음 15자까지 잘리지 않을 수 있습니다.)이 프로세스를 감지하는 다른 방법이 있습니까? (
ps -C
C++, Perl, PHP 및 Bash에 걸쳐 많은 코드와 메소드가 퍼져 있습니다 )
나를 편집하다
그만한 가치가 있는 내용은 /proc/<pid>/stat
잘린 파일 이름을 표시합니다.
cat /proc/4605/stat
4605 (DvBuildSegmentL) S 25769 4605 25769 34817 4605 1077936384 10536 304 0 0 225 119 0 0 20 0 1 0 6717759 103620608 10945 18446744073709551615 4194304 4339868 140734307933616 0 0 0 0 4096 16901 1 0 0 17 4 0 0 0 0 0 6438088 6440229 11730944 140734307937640 140734307937666 140734307937666 140734307938275 0
그러나 /proc/<pid>/cmdline
앞에는 전체 경로가 있지만 전체 명령 이름은 있습니다.
cat -v /proc/4605/cmdline
/usr/local/blah/blah/blah/DvBuildSegmentList^@-d^@2^@
답변1
이 차이점을 해결하는 한 가지 방법은 procps
패키지의 CentOS 6 버전을 다시 빌드하고 거기서 yum swap
부터 시작하는 것입니다 procps-ng
. 가장 안전한 방법은 아니지만 상당수의 시스템 프로그램을 이전 버전으로 대체합니다.
procps
따라서 완전히 다른 이름으로 다시 빌드하고 설치하기를 원할 수도 있습니다 ps
. 그런 다음 도구를 사용하여 포함 디렉터리가 시스템에 있는지 확인할 /opt/el6-rebuilds/bin/ps
수 있습니다 . 결과는 CentOS 8에서 사용되는 "CentOS 6 동급" 버전이 됩니다 .PATH
/etc/profile.d
ps
그런데 이렇게 말하면 확실히 그런 차이가 있는 걸까요? 방금 RHEL 8에서 이것을 시도했는데 ps -C <program name>
정확히 지정하면 제대로 작동합니다. (실제로 말씀하신 내용은 반대입니다. 부분 문자열을 통해 지정할 때만 작동합니다.)
답변2
이 두 가지 방법은 서로 다른 OS 버전에서 작동하는 것 같습니다.
grep은 프로세스 이름을 얻습니다.
ps aux | grep myLongProcessName | grep -v
프로세스가 실행 중이면 0을 반환하고, 프로세스를 찾을 수 없으면 1을 반환합니다. 두 번째 명령이 grep -v
필요한 이유는 때때로(항상은 아니지만) grep
명령 자체가 의 출력에 나타나기 때문입니다 grep myLongProcessName
.
killall을 통해 신호 0 보내기
killall -0 myLongProcessName
0
프로세스가 존재하는지, 1
아니면 발견되지 않았는지 반환합니다.
"double" 메소드는 실제로 다른 프로세스의 하위 문자열인 경우 grep
실패합니다 . myLongProcessName
예를 들어. 세 가지 프로세스가 있는 경우:
longProcessDBAccess
(실행되지 않음)longProcessDBAccessManager
(달리기)longProcessDBAccessClient
(달리기)
grep
실행 중인지 확인하기 위해 "double" 메소드를 사용하는 것은 longProcessDBAccess
다른 두 메소드의 존재도 감지하기 때문에 실패합니다.
그러나 이 killall
방법이 작동하려면 uid
실행 중인 프로세스에 killall
해당 작업을 수행할 수 있는 권한이 있어야 합니다.
죽이다:
이
kill()
함수는 지정된 프로세스나 프로세스 그룹에 신호를 보내야 합니다pid
. 전송될 신호는 로 지정되며sig
에 제공된 목록의 1 또는 0입니다<signal.h>
. 0(널 신호) 인 경우sig
오류 검사가 수행되지만 실제로 신호가 전송되지 않습니다. 빈 신호를 사용하여 유효성을 확인할 수 있습니다pid
.프로세스가 지정된 프로세스에 신호를 보낼 수 있는 권한을 가지려면
pid
전송 프로세스에 적절한 권한이 없는 한 전송 프로세스의 실제 또는 유효 사용자 ID가 수신 프로세스의 실제 또는 저장된 set-user-ID와 일치해야 합니다.