作為後台工作的一部分,如何讓 bash 重新評估 $(date) - 如果可能的話
作業系統 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 SYSTEM:“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)”-%03u.pdf -" &
我嘗試過單引號、雙引號和無引號。該命令使用所有三個選項啟動。但是,單引號和雙引號產生相同的結果,時間戳固定為命令啟動的時間。不帶引號的命令會啟動,但發送給它的任何內容都會導致源源不斷的損壞管道錯誤:
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
我從中收集到一個外殼是分叉的,但在啟動時會分叉一次。這就是每次數據流到達時都沒有評估 $() 構造的原因嗎?反正有這個限制嗎?
您的引號不會影響
$(date)
命令,因此它總是在命令執行前立即評估一次socat
。出於說明目的簡化您的命令,我希望這是一個稍微簡單的視圖,顯示
$(date)
引號內的socat TCP4-LISTEN:flags SYSTEM:"sed | gpcl6 file-"$(date)"-suffix" # ^in quotes ^out ^in ^out
如果將它放在雙引號內,它將像現在一樣被評估(除了結果輸出中的任何空格將保留為空格而不是單詞分割點)。如果你把它放在單引號內,
socat
呼叫來評估SYSTEM
選項的 shell 將在每次呼叫它時評估它:socat TCP4-LISTEN:flags SYSTEM:'sed | gpcl6 file-$(date)-suffix'
您可以使用這對命令看到這一點,在兩個不同的系統上執行:
# 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 -' &