GNU/Linux >> Linux の 問題 >  >> Linux

プロセス置換を実現するためのポータブル(posix)の方法?

bashなどの一部のシェル 、次のように、プロセス出力をファイルとして表示する方法であるプロセス置換をサポートします。

$ diff <(sort file1) <(sort file2)

ただし、この構成はPOSIXではないため、移植性はありません。 POSIXに適した方法でプロセス置換を実現するにはどうすればよいですか (つまり、/bin/shで機能するもの )

注:質問は、2つのソートされたファイルを比較する方法を尋ねているのではありません。これは、プロセス置換を示すための考案された例にすぎません!

承認された回答:

この機能はkshによって導入されました (ksh86で最初に文書化されました)そして/dev/fd/n 機能
(以前の一部のBSDおよびAT&Tシステムで個別に追加されました)。
kshで ksh93uまでは、システムが/dev/fd/n 。 zsh、bash、およびksh93u+ 以上は、/dev/fd/n 利用できません。

/dev/fd/n が利用可能です(POSIXはそれらを指定していません)。
プロセス置換を実行できます(例:diff <(cmd1) <(cmd2) )自分自身:

{
  cmd1 4<&- | {
    # in here fd 3 points to the reading end of the pipe
    # from cmd1, while fd 0 has been restored from the original
    # stdin (saved on fd 4, now closed as no longer needed)

    cmd2 3<&- | diff /dev/fd/3 -

  } 3<&0 <&4 4<&- # restore the original stdin for cmd2

} 4<&0 # save a copy of stdin for cmd2

ただし、これはksh93では機能しません Linuxの場合、シェルパイプは、パイプの代わりにソケットペアを使用して実装され、/dev/fd/3を開きます。 ここで、fd3がソケットを指している場合はLinuxでは機能しません。

POSIXは/dev/fd/n 、名前付きパイプを指定します。名前付きパイプは、ファイルシステムからアクセスできることを除けば、通常のパイプと同じように機能します。ここでの問題は、一時的なものを作成して後でクリーンアップする必要があることです。これは、特にPOSIXに標準のメカニズム(mktemp -dなど)がないことを考えると、確実に行うのは困難です。 一部のシステムで見られるように)一時ファイルまたはディレクトリを作成し、信号処理(ハングアップまたは強制終了時にクリーンアップする)も移植可能に行うのは困難です。

次のようなことができます:

tmpfifo() (
  n=0
  until
    fifo=$1.$$.$n
    mkfifo -m 600 -- "$fifo" 2> /dev/null
  do
    n=$((n + 1))
    # give up after 20 attempts as it could be a permanent condition
    # that prevents us from creating fifos. You'd need to raise that
    # limit if you intend to create (and use at the same time)
    # more than 20 fifos in your script
    [ "$n" -lt 20 ] || exit 1
  done
  printf '%s\n' "$fifo"
)

cleanup() { rm -f -- "$fifo"; }

fifo=$(tmpfifo /tmp/fifo) || exit

cmd2 > "$fifo" & cmd1 | diff - "$fifo"

cleanup

(ここでは信号処理は行いません)。

関連:ターミナルを開いた直後にプロセスが完了し、コマンドを追加できませんか?
Linux
  1. プロセス置換とパイプ?

  2. Sed、Awk、Perl、Shの中で最もポータブルなのはどれですか?

  3. プロセスIDの最大値は?

  1. Linux –デフォルトルートの送信元アドレスを取得するためのポータブルな方法?

  2. プロセス置換の出力が正常ではありませんか?

  3. Isoを抽出する最速の方法は?

  1. Linux Mint 20.3にアップグレードする方法:正しい方法

  2. 親プロセスが終了したときの新しい親プロセス?

  3. Unix で別のプロセスの環境変数を変更する方法はありますか?