操作系统 FreeBSD-12.2
我有一个使用 的虚拟打印机设置socat
。该socat
命令在后台运行。它生成一个系统 shell,用于处理输入流并将其发送到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_ljiii_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
据我所知,shell 是分叉的,但在启动时就分叉了一次。这就是每次数据流到达时 $() 构造不被评估的原因吗?无论如何,有这个限制吗?
答案1
您的引号不会影响$(date)
命令,因此它总是在socat
执行命令之前立即计算一次。
出于说明目的简化您的命令,我希望这是一个稍微简单的视图,显示如何$(date)
不在引号内
socat TCP4-LISTEN:flags SYSTEM:"sed | gpcl6 file-"$(date)"-suffix"
# ^in quotes ^out ^in ^out
如果将其放在双引号内,它将像现在一样进行评估(除了结果输出中的任何空格将保留为空格而不是单词分割点)。如果将其放在单引号内,socat
则调用来评估该选项的 shellSYSTEM
将在每次调用时对其进行评估:
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 -' &