パイププロセスでシェルを開くことができないのはなぜですか?

パイププロセスでシェルを開くことができないのはなぜですか?

私の問題を次のコードに圧縮しました。

#include <stdio.h>

int main(){
    char buffer[256];

    printf("Enter input: ");
    scanf("%s", buffer);

    system("/bin/sh");
    return 0;
}

ユーザー入力でプログラムを実行すると、次のような結果が得られます。

user@ubuntu:~/testing/temp$ ./main
Enter input: Test
$ 

最後の行はプログラムが起動されるシェルです。

ただし、パイプの入力としてプログラムを実行すると、次のようになります。

user@ubuntu:~/testing/temp$ echo 'test' | ./main
Enter input: user@ubuntu:~/testing/temp$

プログラムがシェルを開いていないようです。


少し悩んだ後、私は次の事実に気づきました。

user@ubuntu:~/testing/temp$ (python -c "print 'test'" ; echo 'ls') | ./main
a.out  main  main.c
Enter input: user@ubuntu:~/testing/temp

ls開いたシェルからコマンドを実行できます。

したがって、2つの質問があります。

  1. 最初のケースのようにシェルが開かないのはなぜですか?
  2. この問題にどのように対処する必要がありますか?実行するコマンドを決定する必要があるのは非常に不便です。今後プログラムの実行:私は実行するコマンドを動的に選択できるシェルが欲しいです。

ベストアンサー1

  1. 最初のケースのようにシェルが開かないのはなぜですか?

最初のケースstdinは、端末とシェルが対話型であることです。それはあなたの命令などを待ちます。

2番目のケースstdinはパイプで、シェルは非対話型です。プログラムは最初の行stdin(文字列test\n)を消費し、シェルがそれを読み取ろうとし、stdinそれを確認しますEOF。これは、入力を受け取るプログラムがEOF実行する必要がある操作であるためです。

3番目の場合でも、同じ理由でシェルは再び非対話型になります。つまり、その行の最初の行を消費し、シェルがそれをscanf()読み取ります。シェルが実行され、より多くのコマンドを読み取ろうとし、確認して終了します。stdintest\nlslsEOF

  1. この問題にどのように対処する必要がありますか?

「処理」とは、stdinパイプに接続している間に対話型シェルを実行することを意味する場合、解決策はpty(7)

おすすめ記事