為什麼在終止進程時告訴我非法 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

我嘗試像這樣調整終止進程命令(xargs 修剪 pid 的空格)以刪除 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"- 這將防止_NAMEshell 將其解釋為變數名稱的一部分。

  2. 您正在使用反引號而不是$().它們已被棄用多年,並且有充分的理由。它們不是問題的根源,只是您需要戒掉的壞習慣。

  3. cut不是提取可由 1 個或多個字元分隔的欄位的好工具。僅當欄位之間只有一個(並且恰好是一個)分隔符號時才有效。許多文字檔案使用 1 個或多個空格(和/或製表符和/或其他空白字元)作為欄位分隔符,並且不能輕鬆地使用cut.使用awkperl代替。

    您使用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}'放置 a可以防止 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由於or返回多個 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

相關內容