セロリには多くのプロセスがあるので、サーバーでセロリを再起動したいと思います。すべてのプロセスIDを照会して終了するために、次のスクリプトを作成しました。
#
# stop celery process
#
PID=`ps -ef|grep -w ${CELERY_PROGRAM_NAME}|grep -v grep|cut -c 9-15`
if [ -z "${PID}" ]; then
echo "Process aready down..."
else
array=(${PID//\n/})
for var in "${array[@]}"
do
single_pid=`echo ${var} | awk 'gsub(/^ *| *$/,"")' `
if [[ ${single_pid} -gt 1 ]]; then
kill -15 "${single_pid}"
else
echo "Process ${PROGRAM_NAME} not found"
fi
done
fi
ログでpidが配列に変換されておらず、次のステップが正しく分割されていないことがわかりました。 GitHub Actionsでリモートでこのスクリプトを実行します。以下はGitHub Actionsのログ出力です。
======CMD======
cd /opt/apps/pydolphin
. /opt/apps/pydolphin/restart.sh
======END======
err: +/opt/apps/pydolphin/restart.sh:16> PROGRAM_NAME=schedulespider.py
err: +/opt/apps/pydolphin/restart.sh:17> CELERY_PROGRAM_NAME=celery
err: +/opt/apps/pydolphin/restart.sh:18> PYTHON_BIN_PATH=/usr/bin/python3
err: +/opt/apps/pydolphin/restart.sh:23> PID=+/opt/apps/pydolphin/restart.sh:23> ps -ef
err: +/opt/apps/pydolphin/restart.sh:23> PID=+/opt/apps/pydolphin/restart.sh:23> grep -w celery
err: +/opt/apps/pydolphin/restart.sh:23> PID=+/opt/apps/pydolphin/restart.sh:23> grep -v grep
err: +/opt/apps/pydolphin/restart.sh:23> PID=+/opt/apps/pydolphin/restart.sh:23> cut -c 9-15
err: +/opt/apps/pydolphin/restart.sh:23> PID=' 9777
err: 9778
err: 9779
err: 9865
err: 9867
err: 9868 '
err: +/opt/apps/pydolphin/restart.sh:24> [ -z ' 9777
err: 9778
err: 9779
err: 9865
err: 9867
err: 9868 ' ']'
err: +/opt/apps/pydolphin/restart.sh:27> array=( ' 9777
err: 9778
err: 9779
err: 9865
err: 9867
err: 9868 ' )
err: +/opt/apps/pydolphin/restart.sh:28> var= 9777
err: 9778
err: 9779
err: 9865
err: 9867
err: 9868
err: +/opt/apps/pydolphin/restart.sh:30> single_pid=+/opt/apps/pydolphin/restart.sh:30> echo ' 9777
err: 9778
err: 9779
err: 9865
err: 9867
2021/07/19 06:00:52 Process exited with status 1
err: 9868 '
err: +/opt/apps/pydolphin/restart.sh:30> single_pid=+/opt/apps/pydolphin/restart.sh:30> awk 'gsub(/^ *| *$/,"")'
err: +/opt/apps/pydolphin/restart.sh:30> single_pid='9777
err: 9778
err: 9779
err: 9865
err: 9867
err: 9868'
err: +/opt/apps/pydolphin/restart.sh:31> [[ '9777
err: 9778
err: 9779
err: 9865
err: 9867
err: 9868' -gt 1/opt/apps/pydolphin/restart.sh:31: bad math expression: operator expected at `9778\n9779\n...'
err: ]]
スクリプトを読みましたが、何が間違っているのかわかりませんでした。スクリプトを機能させるにはどうすればよいですか?
答え1
単にを使用する代わりに独自の「終了ループ」を作成することを決定した場合は、少なくとも次pkill
のpgrep
出力を分割し、分割は代わりに可能な先行/末尾のスペースによって妨げられないPIDのリストを取得するために使用しますps
。
array=($(pgrep -- "${CELERY_PROGRAM_NAME}"))
pgrep
または、出力を直接繰り返します。
for single_pid in $(pgrep -- "${CELERY_PROGRAM_NAME}"); do ...
pgrep
1行に1つずつPIDリストを作成します。デフォルトの bash IFS は連続した空白に分割されます。改行を含むたとえば、配列にマップします。
$ pgrep ssh
1194
3688
22642
22754
$ array=($(pgrep ssh))
$ declare -p array
declare -a array=([0]="1194" [1]="3688" [2]="22642" [3]="22754")
または使用できますreadarray -t array < <(pgrep ssh)
。
要素がないとループは実行されないため、文字列が空であることをテストする必要はありません。
実装が機能しない理由は1${PID//\n/}
からリテラルn
文字が削除されます。数値のみを含むと仮定すると、何もできません。PID
PID
array=(${PID//\n/})
しなければならないsingle_pid
PIDを取得するために追加の処理を必要としないように、別々のPID配列が作成され、先行スペースと末尾のスペースが削除されます。
エラー出力によると、明らかにそうではないという事実は、次の2つの理由の1つを示唆しています。
シェルのIFS値を修正しました。
使用中のシェルは、引用符のない変数拡張をトークン化しません。
zsh
、出力形式は、デフォルトのxtrace
動作としてファイルを使用していることを示します。つまり、コマンドの置き換え時にIFS分割を実行しても、上記のコードはそのシェルで動作し続けます。から改行に分割するには、zsh
次を使用することをお勧めします。array=(${(f)"$(pgrep -- $CELERY_PROGRAM_NAME)"})
ただし、これは現在の値への依存関係を
bash
排除します。readarray
$IFS
1実際に改行文字を削除するには、以下を使用できます。${PID//$'\n'/}
答え2
避けるべきもう1つのオプションはpgrep/pkill
カスタム出力ですps
。
ps
リストプロセスと印刷フォーマット/フィールドでカスタマイズを実行できます。
多くのフィールドを持つすべてのプロセスが一覧表示されるため、ps -ef
pidを取得するのは面倒です。
whileはps -e -o pid,comm
2つの出力列を提供します
PID COMMAND
1 systemd
2 kthreadd
3 rcu_gp
4 rcu_par_gp
9 mm_percpu_wq
10 ksoftirqd/0
(...)
1002 gdm3
1013 sshd
1031 php-fpm7.4
1032 php-fpm7.4
1044 nginx
1065 nmbd
(many more lines)
(または-o pid= -o comm=
タイトルを削除してください)。
私が探しているプロセスが次の場所にあり、${CELERY_PROGRAM_NAME}
バックスラッシュやスペース文字が含まれていない場合は、次のものを使用できます。
ps -e -o pid= -o comm= | awk -v proc="${CELERY_PROGRAM_NAME}" '$2==proc { print $1}'
PIDを入手してください。
使用
PID=$(ps -e -o pid= -o comm= | awk -v proc="${CELERY_PROGRAM_NAME}" '$2==proc { print $1})
空でないことを確認したら、これが${PID}
改行で区切られたpidリストであることを考慮して、次のものを使用できます(デフォルトでは$IFS
改行が含まれていると仮定)。
for pid2 in ${PID}
do
...
done
(出力として使用することを推奨するzsh
形式を使用している場合は、デフォルトでdo -splittingに置き換えるか、値に関係なく改行に分割するように変更してください。)xtrace
${PID}
${=PID}
$IFS
bash
${(f)PID}
$IFS
選ぶ
一部のオプションps
(man ps
すべて表示)
ps -p 1234 -o tty,args
(pid 1234のttyとargsのリスト)ps -t pts/1,pts/3 -f
(tty pts / 1とpts / 3にすべての内容を一覧表示)ps -u archemar
(archemarに属するすべてのプロセスのリスト)
HP / UXおよびprocpsの実装は、名前に基づいてプロセスを照会するオプションもps
サポートしています。-C