オペレーティングシステムFreeBSD-12.2
私が使用する仮想プリンタ設定がありますsocat
。このsocat
コマンドはバックグラウンドで実行されます。入力ストリームを処理してそれを送信してgpcl6
PDF文書を生成するシステムシェルを作成します。出力は特定のディレクトリのファイルに移動されます。ファイル名にはタイムスタンプを含める必要があります$(date -Iseconds)
。問題は、このタイムスタンプは、コマンドのsocat
開始後にのみ計算され、その後はカウントされないことです。私の質問は:データストリームが到着するたびに再評価する方法はありますか?
完全なコマンドは次のとおりです。
HPNP=4178 socat TCP4-LISTEN:4178,bind=192.168.216.179,fork,reuseaddr,su=hp3000 システム: "sed -r '1s/^.{42}//' | cat /var/spool/hp3000/forms /hll_inv_ljiiii_85.ovl - | gpcl6 -dNOSAFE -dNOPAUSE -sDEVICE=pdfwrite -sOutputFile=/var/spool/hp3000/np4178/HP3000-INV-"$(date -Iseconds)" - %0
一重引用符、二重引用符、引用符なしを試しました。コマンドは3つのオプションすべてで始まります。ただし、一重引用符と二重引用符は同じ結果を生成し、タイムスタンプはコマンドが開始された時刻に固定されます。引用符がないと、コマンドは開始されますが、コマンドに送信されたすべてのエントリーはパイプの破損エラーを継続的に発生させます。
2021/05/17 15:56:55 socat[17557] E write(5, 0x800b09000, 1460): Broken pipe
cat: stdout: Broken pipe
sed: stdout: Broken pipe
socat のマニュアルページには次のものがあります。
SYSTEM:<shell-command>
Forks a sub process that establishes communication with its
parent process and invokes the specified program with system() .
Please note that <shell-command> [string] must not contain ','
or "!!", and that shell meta characters may have to be
protected. After successful program start, socat writes data to
stdin of the process and reads from its stdout.
Option groups: FD,SOCKET,EXEC,FORK,TERMIOS
Useful options: path, fdin, fdout, chroot, su, su-d, nofork,
pty, stderr, ctty, setsid, pipes, sigint, sigquit
See also: EXEC
私が知る限り、シェルはフォークされますが、起動時に一度だけ発生します。これは、データストリームが到着するたびに$()構成が評価されない理由ですか?とにかく、これにも限界はありますか?
答え1
引用符は$(date)
コマンドに影響を与えないため、常にsocat
コマンドを実行する直前に評価されます。
$(date)
説明の目的で、コマンドを単純化するために引用符を使用しない方法を示す少し簡単なビューになることを願っています。
socat TCP4-LISTEN:flags SYSTEM:"sed | gpcl6 file-"$(date)"-suffix"
# ^in quotes ^out ^in ^out
二重引用符の中に入れると、今のように評価されます(ただし、結果出力の空白は単語区切りではなく空白のままです)。一重引用符に入れると、オプションsocat
を評価するために呼び出されたシェルはすべての呼び出しSYSTEM
でオプションを評価します。
socat TCP4-LISTEN:flags SYSTEM:'sed | gpcl6 file-$(date)-suffix'
2つの異なるシステムで実行されているこのコマンドのペアを使用して、それらを実際に確認できます。
# Server
socat TCP4-LISTEN:4178,fork,reuseaddr SYSTEM:'cat >socat.$(date +%H%M%S).txt'
# Client
echo boo | nc remoteServer 4178
# Sever
ls șocat.*.txt
この変更を元のコードに再適用すると、次のような結果が得られます(便宜上、コマンドで使用される引用符の種類も変更しましたsed
)。
HPNP=4178 socat TCP4-LISTEN:4178,bind=192.168.216.179,fork,reuseaddr,su=hp3000 SYSTEM:'sed -r "1s/^.{42}//" | cat /var/spool/hp3000/forms/hll_inv_ljiii_85.ovl - | gpcl6 -dNOSAFE -dNOPAUSE -sDEVICE=pdfwrite -sOutputFile=/var/spool/hp3000/np4178/HP3000-INV-$(date -Iseconds)-%03u.pdf -' &