LoginSignup
0
0

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

Last updated at Posted at 2023-10-10

終了ステータスとは?

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

// 終了ステータス "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を得られます。

#include <libc.h>
int	main(void)
{
	int cmd_num = 2; // number of command
	int index = 0;
	int exit_number = 0;
	int pid[cmd_num];
	int last_pid;

	while (index < cmd_num)
	{
        pipe(pid);
		pid[index] = fork();
		last_pid = pid[index];
		if (pid[index] == 0) // child proccess
		{
            // 子プロセス用のシグナルにする (signal, sigaction)
			// connect pipe (dup2, close)
			// connect redirect (dup2)
			// do command (execve)
            // put the exit_number
			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

0
0
7

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0