このコマンドをスクリプトで実行すると、ps
のヘッダー以外の出力は生成されません。
# Taken from Advanced Bash Usage on youtube:
echo "$(echo "$(echo "$(echo "$(ps wwf -s $$)")")")"
これは出力です:
$./testing.bash
PID TTY STAT TIME COMMAND
しかし、ここでは期待される出力を生成するターミナルで実行されます:
$echo "$(echo "$(echo "$(echo "$(ps wwf -s $$)")")")"
PID TTY STAT TIME COMMAND
18289 pts/4 Ss+ 0:00 /bin/bash
17917 pts/4 S+ 0:00 \_ /bin/bash
17918 pts/4 S+ 0:00 \_ /bin/bash
17919 pts/4 S+ 0:00 \_ /bin/bash
17920 pts/4 S+ 0:00 \_ /bin/bash
17921 pts/4 R+ 0:00 \_ ps wwf -s 18289
質問:
違いを説明して、正しい方法を教えていただけますか?
私は多くのことを試し、グーグルを4時間検索しました。必要に応じて、私が試したことをリストアップできますが、ここでは関係ないと思います。
$echo $Shell
/bin/bash
そして:
$head -1 testing.bash
#!/bin/bash
ps
'-s sessionid
オプションは、セッションIDに基づいてプロセスを選択することです。
ps -j
を使用して、プロセスのセッションIDを確認できます。プロセスグループと共にセッションは、通常、シェルジョブ制御に使用されます(つまり、-j
)。
ターミナルエミュレータは、プロセスを使用して新しいセッションを作成し、それを再利用して優先シェルを実行します。したがって、ターミナルでは、セッションIDは通常、そのシェルのpidと同じになります。
つまり、ps -j -s "$$"
をthatシェルで実行すると、"$$"
happensセッションIDと同じです。
他のシェル(testing
スクリプトを解釈するために子プロセスで実行されるシェルなど)、セッションリーダーではないシェルでそのコマンドを実行すると、セッションがないため何も得られません。そのシェルのpidに対応するidを持ちます。
$ ps -j -s "$$"
PID PGID SID TTY TIME CMD
7239 7239 7239 pts/7 00:00:00 zsh
21002 21002 7239 pts/7 00:00:00 ps
$$
は、セッションリーダーである7239です。つまり、ps -j -s 7239
は、そのセッションのすべてのプロセスを提供します。
$ sh -xc 'ps -j -s "$$"; ps -j -p "$$"'
+ ps -j -s 21044
PID PGID SID TTY TIME CMD
+ ps -j -p 21044
PID PGID SID TTY TIME CMD
21044 21044 7239 pts/7 00:00:00 sh
2番目のps
が示すように、最初のps
コマンドは何も返しません。id21044のプロセスはセッションリーダーではないため、id 21044のセッションはありません。セッションリーダーは7239のままで、シェルはターミナルエミュレーターによって起動されます。
$ sh -xc 'ps -j -s "$(($(ps -o sid= -p "$$")))"'
+ ps -o sid= -p 21215
+ ps -j -s 7239
PID PGID SID TTY TIME CMD
7239 7239 7239 pts/7 00:00:00 zsh
21215 21215 7239 pts/7 00:00:00 sh
21217 21215 7239 pts/7 00:00:00 ps
これで、セッションのすべてのプロセスが表示されます。 ps -o sid= -p "$$"
を使用して、$$
が属するセッションのIDを取得しました。