0

多段パイプの終了ステータス実装

投稿日

終了ステータスとは?

スクリプトが終了したときに、スクリプトを実行したツールに返される値。

// 終了ステータス "0"
int main(){
	return (0);
}
// 終了ステータス "1"
int main(){
	return (1);
}

基本的な終了ステータスの種類は以下の通りです。[1]

終了ステータス 意味
0 正常終了
1 一般的なエラー
2 シェルビルトインの誤用
126 呼び出されたコマンドが実行できない
127 コマンドが見つからない
"command not found"
128 無効な終了引数
128+n シグナル終了ステータス
130 Control-Cでスクリプトを終了
255 終了ステータスが範囲外
(範囲は0 ~ 255)

終了ステータスの確認方法

shellの特殊変数 $? に終了ステータスが入っています。

echoコマンドで確認することができます。

echo $?

先ほどのコードをコンパイルして終了ステータスを確認してみます。

bash-3.2$ cat test.c
int main(){
  return (1);
}
bash-3.2$ gcc test.c
bash-3.2$ ./a.out
bash-3.2$ echo $?
1

しっかりと1が終了ステータスに格納されているのがわかります。

パイプがあるときの終了ステータス

パイプがある際に終了ステータスは
コマンドの実行速度などには関係なく、
パイプを繋いだ最後のコマンド(一番右のコマンド)の終了ステータスになります。

以下の場合は、右のコマンドの終了ステータスが表示されるので1が返ってきます。

bash-3.2$ exit 0 | exit 1
bash-3.2$ echo $?
1

シグナルでコマンドが終了してもこの原則は変わりません。

# Control-Cでスクリプトを終了 -> 終了ステータス130
bash-3.2$ cat
^C
bash-3.2$ echo $?
130

# echo abc が正常終了しているから0が返ってきます。
bash-3.2$ cat | echo abc
abc
^C
bash-3.2$ echo $?
0

また、多段パイプでも同じことが言えます。

bash-3.2$ exit 0 | exit 21 | exit 42
bash-3.2$ echo $?
42

実装

以下では、C言語で多段パイプを実装します。

使用関数は、以下のものを仕様します。

pipe, fork, dup, dup2, wait, open, close

概要程度になりますが、以下のように実装することができます。

以下の実装では、forkした際に得られるプロセスIDをpid[index]に格納し、

最後にwhile文を通ったそのコマンドこそがlast_pidになるはずです。

そして、そのlast_pidをwaitすることにより、exit_statusを得られます。

void	main_loop(cmd_num)
{
  int index = 0;
  int exit_number;
  int pid[cmd_num];
  int last_pid;

	while (index < cmd_num)
	{
		pid[index] = fork();
		last_pid = pid[cmd_num];
		if (pid[index] == 0) // child proccess
    {
      // connect pipe
      // connect redirect
      // do command
      exit(exit_number);
    }
    index++;
	}
  
  index = 0;
  int exit_status;
  int status;
	while (index < cmd_num) // wait in parent proccess
	{
		if (wait(&status) == last_pid)
			exit_status = WEXITSTATUS(status);
		index++;
	}
  return (exit_status);
}

追伸

私がbashの簡易実装を行なったレポジトリです。(たぶん似たコードがあるはずですw)↓

よければスターをつけていただければ幸いです。。。

引用
[1]:https://tldp.org/LDP/abs/html/exitcodes.html

新規登録して、もっと便利にQiitaを使ってみよう

  1. あなたにマッチした記事をお届けします
  2. 便利な情報をあとで効率的に読み返せます
ログインすると使える機能について

コメント

この記事にコメントはありません。
あなたもコメントしてみませんか :)
新規登録
すでにアカウントを持っている方はログイン
0

Qiitaにログインして、便利な機能を使ってみませんか?

あなたにマッチした記事をお届けします

便利な情報をあとから読み返せます