このbashスクリプトでstdinを処理する方法は?

このbashスクリプトでstdinを処理する方法は?

opsinJavaバイナリへの呼び出しのみを管理するbashスクリプト(という名前)があります。すべてのパラメータは${@:1}Javaバイナリに渡されます。

#!/bin/bash
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
java -jar $DIR/../bin-java/opsin/opsin.jar ${@:1}

このバイナリopsin.jarも許可されるstdinので、次のことができます。

echo "abcd" | java -jar opsin.jar

ただし、上記のbashスクリプトを使用して同じことを実行できます。

echo "abcd" | opsin

どのようにstdin渡されますか?

java -jar $DIR/../bin-java/opsin/opsin.jar ${@:1}

Bashスクリプトから?

ベストアンサー1

魔法!

特にシェルはfork(2)これにより、シェルプロセスの2つ(ほとんど)同じコピーが作成されます。特に、サブシェルプロセスは親シェルプロセスの標準入力コピーを継承します。

   *  The child inherits copies of the parent’s set of open file  descrip-
      tors.   Each  file  descriptor  in the child refers to the same open
      file description (see open(2)) as the corresponding file  descriptor
      in  the parent.  This means that the two descriptors share open file
      status flags, current file offset, and signal-driven I/O  attributes
      (see the description of F_SETOWN and F_SETSIG in fcntl(2)).

その後、サブシェルプロセスが呼び出されます。exec(3)Start java、つまりサブシェルプロセス変えるjavaこの呼び出しは、親javaから継承されたファイル記述子のコピーを取得し、渡された標準入力に対して機能できます。

(ファイル記述子に「実行時に閉じる」フラグが設定されていると問題が発生する可能性がありますが、これは標準入力などの標準フラグのデフォルト設定ではありません。)

または、親シェルが実行中にメモリに残る必要がない場合は、javaコードを次のように記述できます。

#!/bin/bash
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
exec java -jar $DIR/../bin-java/opsin/opsin.jar ${@:1}

これはjava、シェルプロセスが不必要にメモリにとどまるのではなく、親シェルプロセスを置き換えます。

詳細については、Apvanced Programming in Unix環境(APUE)に関連するさまざまなフォーク、exec、dup、およびパイプシステムコールに関する章があります。

おすすめ記事