ティーのプロセス交換リストの作成

ティーのプロセス交換リストの作成

複数の異なるサーバーに接続されたpostgresqlデータベースCLIの複数のインスタンスにコマンドをブロードキャストするために使用するこのようなスクリプトがあります。ハードコーディングされたプロセス交換セットを使用しています。

#!/bin/bash
# names have been changed to protect the guilty
cred="user=dbadmin password=SECRET"
domain=example.com

tee \
   >( psql -X "host=db1.$domain dbname=db1 $cred" ) \
   >( psql -X "host=db2.$domain dbname=db2 $cred" ) \
   >( psql -X "host=db3.$domain dbname=db3 $cred" ) \
   >( psql -X "host=xdb1.$domain dbname=xdb1 $cred" ) \
   > /dev/null    
wait

私がしたいのは、forループを使用して代替配列を作成し、次のようにその配列をteeに渡すことです。

tee "${p[@]}" > /dev/null

しかし、ループを使用すると、teeは各項目にエラーを提供するため、$p各項目を取得します。/dev/fd/63

tee: /dev/fd/63: No such file or directory

動作しないコードの例:

p=()
for z in db1 db2 db3 xdb1
do
  p+=( >( psql -X "host=$z.$domain dbname=$z $cred" ) )
done
tee "${p[@]}" > /dev/null

これを行う方法はありますか?

ベストアンサー1

これは次の行で発生します。

  p+=( >( psql -X "host=$z.$domain dbname=$z $cred" ) )

...bashはこの行を完全なコマンドと見なします。プロセスの交換が発生すると、コマンドが完了すると交換されたプロセスのSTDINが閉じます。

私の考えでは、これを行う方法は2つしかありません。

  1. eval。そこに行かないでください。
  2. exec。そこに行こう:

 

p=()
for z in db1 db2 db3 xdb1
do
  exec {fd}> >(psql -X "host=$z.$domain dbname=$z $cred")
  p+=( $fd )
done
cd /dev/fd && exec tee "${p[@]}" >/dev/null

この{fd}>構文を使用すると、bashは新しいファイル記述子を割り当て、その値を割り当てて$fdからそれをプッシュします$p
これで作成する$p必要があるファイルディスクリプタ番号がたくさんあるので、ファイルディスクリプタ番号を実際のファイルに書き込んでから呼び出します。teecd/dev/fdtee

(猫が皮をむく方法はいくつかありますが、これが最初に浮かぶ最も簡単な方法です)

おすすめ記事