labunix's blog

labunixのラボUnix

指定秒数の間ゾンビとなるシェルスクリプトを書いてみた

■指定秒数の間ゾンビとなるシェルスクリプトを書いてみた
 簡単にゾンビプロセスが欲しいときのために。
 init プロセスを里親としている孤児プロセスではありません。
 ポイントは組み込みコマンドの「trap」と「wait」と「&(バックグラウンド実行)」の3つ。

$ bash --version
GNU bash, バージョン 4.4.12(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2016 Free Software Foundation, Inc.
ライセンス GPLv3+: GNU GPL バージョン 3 またはそれ以降 <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

$ man trap | grep -A 8 "^ *trap"; man trap | grep -A 6 "^ *wait"
       trap [-lp] [[arg] sigspec ...]
              シェルがシグナル sigspec を受け取ると、コマンド arg が読み込まれて、実行されます。 arg が存在しない (かつ sigspec  が
              一つ指定された)  場合か、  arg が - の場合、 指定されたシグナルは全てオリジナルの動作 (シェルの起動時に設定されていた
              値) にリセットされます。 arg が空文字列である場合、それぞれの sigspec で指定されたシグナルは、 シェルとシェルが起動し
              たコマンドから無視されます。 arg なしで -p オプションが与えられた場合、 各 sigspec に関連付けられた trap コマンドが表
              示されます。 引き数が全くないか、 -p だけが与えられた場合、 trap は各シグナルに関連付けられたコマンドのリストを出力し
              ます。    -l   オプションを与えると、   シェルはシグナル名と対応する番号のリストを出力します。   それぞれの   sigspec
              は、<signal.h> で定義されているシグナル名、またはシグナル番号です。 シグナル名は大文字小文字は区別されず、先頭の  SIG
              は省略可能です。
       wait [n ...]
              指定された各プロセスを wait し、その終了ステータスを返します。 各 n はプロセス ID またはジョブ指定です。 ジョブ指定を
              与えた場合、そのジョブのパイプラインに含まれる 全てのプロセスを wait します。 n  が与えられていない場合には、現在アク
              ティブな全ての子プロセスを  wait  し、 返却ステータスは 0 となります。 n が存在しないプロセスやジョブを指定している場
              合、 返却ステータスは 127 になります。 それ以外の場合、返却ステータスは wait していた最後のプロセスまたはジョブの終了
              ステータスとなります。

■「zombie.sh」のソース
 sleepとseqの両方で使う引数の正の整数についてのチェックはしてませんので
 ちゃんと秒数で指定して下さい。

$ cat zombie.sh 
#!/bin/bash

function zombie_help(){
  echo -e "Argument: $#"
  echo -e "Usage\t: ./$(basename $0) [zombie-time-number]"
  exit 1
} 

if [ "$#" -ne 1 ];then
  zombie_help
else
  echo "Zombie Time is $1 sec"
fi

echo "$(basename $0) PID=$$"

DELAY=$1
trap "exec sleep $DELAY" EXIT

for n in `seq 1 $DELAY`  ;do
  if [ $n -eq 1 ];then
    pstree -p $$ 
    ps aux | grep "PI[D]"
  fi
  ps aux | grep "defunc[t]"
  sleep 1
done &

trap "exec sleep $DELAY" EXIT &
Zombie=$!
echo "Zombie PID=$Zombie"
exit 0

■実行結果は以下のようになります。

$ ./zombie.sh 5
zombie.sh PID=23691
Zombie PID=23694
sleep(23691)─┬─zombie.sh(23693)───pstree(23696)
             └─zombie.sh(23694)
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
labunix  23694  0.0  0.0      0     0 pts/1    Z+   01:54   0:00 [zombie.sh] <defunct>
labunix  23694  0.0  0.0      0     0 pts/1    Z+   01:54   0:00 [zombie.sh] <defunct>
labunix  23694  0.0  0.0      0     0 pts/1    Z+   01:54   0:00 [zombie.sh] <defunct>
labunix  23694  0.0  0.0      0     0 pts/1    Z+   01:54   0:00 [zombie.sh] <defunct>
labunix  23694  0.0  0.0      0     0 pts/1    Z+   01:54   0:00 [zombie.sh] <defunct>

■一応、引数を与えないと使い方だけ表示して「exit 1」で終了します。

$ ./zombie.sh
Argument: 0
Usage	: ./zombie.sh [zombie-time]