프로세스를 종료할 때 불법 PID를 알려주는 이유는 무엇입니까?

프로세스를 종료할 때 불법 PID를 알려주는 이유는 무엇입니까?

이제 이 스크립트를 사용하여 프로세스를 다시 시작합니다.

PID=`ps -ef|grep -w ${APP_NAME}|grep -v grep|cut -c 9-15`
if [[ ${PID} -gt 1 ]]; then
  kill -9 ${PID}
else
  echo "Process not found"
fi

하지만 GitHub Actions의 원격 서버에서 이 스크립트를 실행하면 다음 오류가 표시됩니다.

======CMD======
cd /opt/apps/dolphin-acientbay/libs
. /opt/apps/dolphin-acientbay/libs/upgrade.sh

======END======
err: +/opt/apps/dolphin-acientbay/libs/upgrade.sh:13> JAVA_HOME=/***/.sdkman/candidates/java/11.0.11.hs-adpt 
err: +/opt/apps/dolphin-acientbay/libs/upgrade.sh:14> APP_HOME=/opt/apps/dolphin-acientbay/libs 
err: +/opt/apps/dolphin-acientbay/libs/upgrade.sh:15> APP_NAME=dolphin-acientbay-service-1.0.0-SNAPSHOT.jar 
err: +/opt/apps/dolphin-acientbay/libs/upgrade.sh:17> PID=+/opt/apps/dolphin-acientbay/libs/upgrade.sh:17> ps -ef
err: +/opt/apps/dolphin-acientbay/libs/upgrade.sh:17> PID=+/opt/apps/dolphin-acientbay/libs/upgrade.sh:17> grep -w dolphin-acientbay-service-1.0.0-SNAPSHOT.jar
err: +/opt/apps/dolphin-acientbay/libs/upgrade.sh:17> PID=+/opt/apps/dolphin-acientbay/libs/upgrade.sh:17> grep -v grep
err: +/opt/apps/dolphin-acientbay/libs/upgrade.sh:17> PID=+/opt/apps/dolphin-acientbay/libs/upgrade.sh:17> cut -c 9-15
err: +/opt/apps/dolphin-acientbay/libs/upgrade.sh:17> PID=' 19882 ' 
2021/05/30 11:46:21 Process exited with status 1
err: +/opt/apps/dolphin-acientbay/libs/upgrade.sh:18> [[ ' 19882 ' -gt 1 ]]
err: +/opt/apps/dolphin-acientbay/libs/upgrade.sh:19> kill -9 ' 19882 '
err: /opt/apps/dolphin-acientbay/libs/upgrade.sh:kill:19: illegal pid:  19882 

이것은 다음의 전체 스크립트입니다 upgrade.sh.

#!/usr/bin/env bash

set -u

set -e

set -x

JAVA_HOME="/root/.sdkman/candidates/java/11.0.11.hs-adpt"
APP_HOME="/opt/apps/dolphin-acientbay/libs"
APP_NAME="dolphin-acientbay-service-1.0.0-SNAPSHOT.jar"

PID=`ps -ef|grep -w ${APP_NAME}|grep -v grep|cut -c 9-15`
if [[ ${PID} -gt 1 ]]; then
  kill -9 ${PID}
else
  echo "Process not found"
fi

sleep 5

count=`ps -ef | grep ${APP_NAME} | grep -v "grep" | wc -l`
if [[ ${count} -lt 1 ]]; then
  nohup ${JAVA_HOME}/bin/java -Xmx128M -Xms128M -jar \
  -Xdebug -Xrunjdwp:transport=dt_socket,suspend=n,server=y,address=0.0.0.0:5021 \
  -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/opt/apps/dolphin-acientbay/ \
  ${APP_HOME}/${APP_NAME} >> ./acientbay.log &
  sleep 5
else
  echo "process aready exists!"
  exit 1
fi

나는 pid의 공백을 제거하기 위해 다음과 같이 kill process 명령을 조정하려고 했습니다(xargs는 pid의 공백을 자릅니다).

 echo "${PID}" | xargs | kill -9

그것은 나에게 말한다 :

err: /opt/apps/dolphin-acientbay/libs/upgrade.sh:kill:19: not enough arguments

답변1

문제의 원인은 다음과 같습니다.

PID=`ps -ef|grep -w ${APP_NAME}|grep -v grep|cut -c 9-15`
  1. 변수를 사용할 때는 큰따옴표를 사용하세요. 예: "$APP_NAME" 또는 "${APP_NAME}".

    그런데 중괄호는 문자열의 다른 텍스트와 변수를 구별해야 할 때만 필요합니다. 예를 들어 변수가 실제로 있지만 $APP문자열에서 사용해야 하는 경우 -를 _NAME사용하면 쉘에서 변수 이름의 일부로 해석되는 것을 방지할 수 있습니다."${APP}_NAME"_NAME

  2. 대신 백틱을 사용하고 있습니다 $(). 그들은 수년 동안 더 이상 사용되지 않았으며 그럴 만한 이유가 있습니다. 이것이 문제의 원인이 아니라, 그만둬야 할 나쁜 습관일 뿐입니다.

  3. cut1개 이상의 문자로 구분될 수 있는 필드를 추출하는 데는 좋은 도구가 아닙니다. 필드 사이에 구분 기호가 하나(정확히 하나)인 경우에만 유용합니다. 많은 텍스트 파일은 필드 구분 기호로 1개 이상의 공백(및/또는 탭 및/또는 기타 공백 문자)을 사용하므로 로 쉽게 처리할 수 없습니다 cut. 대신 awk또는 를 사용하세요 perl.

    를 사용하면 cut -c 9-15$PID에 하나 이상의 추가 공백 문자가 캡처됩니다. 에서 PID를 추출하려면 대신을 ps -ef사용하십시오 .awk '{print $2}'cut -c 9-15

  4. pgrep "$APP_NAME"이름으로 프로세스의 PID를 가져오는 데 사용됩니다 . 또는 pgrep -f "$APP_NAME"검색 중인 문자열이 인수인 경우(예: 스크립트 이름이 인터프리터에 인수로 전달되는 경우).

    화물 선별은 ps | grep ... | grep -v grep이제 수십 년 동안 쓸모가 없어졌으며 어쨌든 결코 좋은 방법이 아니었습니다. ps -ef | awk '/[p]rocess_name/ {print $2}'항상 더 나은 방법이었습니다( []패턴의 첫 번째 문자 주위에 를 배치하면 awk, grep 등이 ps 출력에서 ​​자체적으로 일치하는 것을 방지할 수 있음). 그러나 이제 그 방법도 pgrep.

    ps자체에는 -C프로세스 이름 일치 옵션, h헤더 억제 옵션, -o원하는 출력을 지정하는 옵션이 있습니다 ps. 예를 들어ps h -o pid -C "$APP_NAME"

모든 것을 요약하려면 다음을 사용하십시오.

    PID=$(pgrep "$APP_NAME")
or
    PID=$(pgrep -f "$APP_NAME")
or
    PID=$(ps h -o pid -C "$APP_NAME")

그런데, 있다면어느pgrep또는 에 의해 여러 PID가 반환될 가능성이 있으므로 ps출력을 스칼라 변수가 아닌 배열로 캡처해야 합니다. 예를 들어, 다음은 표시되는 모든 bash 프로세스의 PID를 배열로 캡처합니다 $BASHPIDS.

$ BASHPIDS=( $(ps h -o pid -C bash) )

$ typeset -p BASHPIDS
declare -a BASHPIDS=([0]="68910" [1]="71059" [2]="71634" [3]="71641" [4]="71643"
[5]="71680" [6]="71683" [7]="71684" [8]="71687" [9]="71693" [10]="71712" [11]="72394"
[12]="72568" [13]="72589" [14]="970222" [15]="974740" [16]="1078757" [17]="1278073"
[18]="1365082" [19]="1405642" [20]="1458889" [21]="2278763" [22]="2466442" [23]="2876831"
[24]="2955565" [25]="3260896" [26]="3261235" [27]="3269020" [28]="3281961" [29]="3702104" 
[30]="4038149")

어떤 이유로든 그들을 모두 죽이고 싶다면 다음을 사용하여 그렇게 할 수 있습니다.

kill "${BASHPIDS[@]}"

답변2

이 명령은 문제를 해결합니다.

 echo "${PID}" | xargs kill -9

관련 정보