BashのPIDが配列に分割されない理由

BashのPIDが配列に分割されない理由

セロリには多くのプロセスがあるので、サーバーでセロリを再起動したいと思います。すべてのプロセス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

単にを使用する代わりに独自の「終了ループ」を作成することを決定した場合は、少なくとも次pkillpgrep出力を分割し、分割は代わりに可能な先行/末尾のスペースによって妨げられないPIDのリストを取得するために使用しますps

array=($(pgrep -- "${CELERY_PROGRAM_NAME}"))

pgrepまたは、出力を直接繰り返します。

for single_pid in $(pgrep -- "${CELERY_PROGRAM_NAME}"); do ...

pgrep1行に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文字が削除されます。数値のみを含むと仮定すると、何もできません。PIDPIDarray=(${PID//\n/}) しなければならないsingle_pidPIDを取得するために追加の処理を必要としないように、別々のPID配列が作成され、先行スペースと末尾のスペースが削除されます。

エラー出力によると、明らかにそうではないという事実は、次の2つの理由の1つを示唆しています。

  1. シェルのIFS値を修正しました。

  2. 使用中のシェルは、引用符のない変数拡張をトークン化しません。zsh、出力形式は、デフォルトのxtrace動作としてファイルを使用していることを示します。つまり、コマンドの置き換え時にIFS分割を実行しても、上記のコードはそのシェルで動作し続けます。から改行に分割するには、zsh次を使用することをお勧めします。

    array=(${(f)"$(pgrep -- $CELERY_PROGRAM_NAME)"})
    

    ただし、これは現在の値への依存関係をbash排除します。readarray$IFS


1実際に改行文字を削除するには、以下を使用できます。${PID//$'\n'/}

おすすめ記事