TCL 脚本中断 "child killed: write on pipe with no readers"
TCL script breaks with "child killed: write on pipe with no readers"
升级到 Debian Jessie 后,我设置的 tcl motd 在登录时给我一个 st运行ge 错误 (主机名空白):
root pts/0 XXXX-XX-XX-XXX-X Thu Jun 23 01:49:55 2016 - Thu Jun 23 01: 50:09 2016 (00:00)
child killed: write on pipe with no readers
while executing
"exec -- last -F | head -n 2 | tail -n 1 "
invoked from within
"set lastlog [exec -- last -F | head -n 2 | tail -n 1 ]"
(file "/etc/motd.tcl" line 24)
我很困惑,因为 运行 我自己得到了打印在顶部的确切行,但是当 运行 作为脚本的一部分时它不应该打印任何东西,而是将其设置为变量的值,正如您从错误中引用的行中看到的那样:
set lastlog [exec -- last -F | head -n 2 | tail -n 1 ]
这里发生了什么导致神秘错误,我该如何解决?
错误是由一个以非零退出代码终止的子进程引起的(exec
对此非常敏感),而这又是由于尽管有管道,它仍然有输出要产生被关闭(使用 head
的常见问题)。最简单的解决方法是将 last -F
的整个输出读入 Tcl 并在那里截断行。幸运的是,这很容易:
set lastOutputLines [split [exec -- last -F] "\n"]
set lastlog [lindex $lastOutputLines 1]; # Zero-based indexing
只要 last
的输出不是很大,这就足够快了。
您可以使用子 shell 调用,其中 shell 不介意第一个命令通过信号终止,如:
set lastlog [exec -- bash -c "last -F | head -n 2 | tail -n 1"]
这样做的好处是可以在 "last" 发出其全部输出之前实际终止执行,如果输出很长,这很好。
升级到 Debian Jessie 后,我设置的 tcl motd 在登录时给我一个 st运行ge 错误 (主机名空白):
root pts/0 XXXX-XX-XX-XXX-X Thu Jun 23 01:49:55 2016 - Thu Jun 23 01: 50:09 2016 (00:00)
child killed: write on pipe with no readers
while executing
"exec -- last -F | head -n 2 | tail -n 1 "
invoked from within
"set lastlog [exec -- last -F | head -n 2 | tail -n 1 ]"
(file "/etc/motd.tcl" line 24)
我很困惑,因为 运行 我自己得到了打印在顶部的确切行,但是当 运行 作为脚本的一部分时它不应该打印任何东西,而是将其设置为变量的值,正如您从错误中引用的行中看到的那样:
set lastlog [exec -- last -F | head -n 2 | tail -n 1 ]
这里发生了什么导致神秘错误,我该如何解决?
错误是由一个以非零退出代码终止的子进程引起的(exec
对此非常敏感),而这又是由于尽管有管道,它仍然有输出要产生被关闭(使用 head
的常见问题)。最简单的解决方法是将 last -F
的整个输出读入 Tcl 并在那里截断行。幸运的是,这很容易:
set lastOutputLines [split [exec -- last -F] "\n"]
set lastlog [lindex $lastOutputLines 1]; # Zero-based indexing
只要 last
的输出不是很大,这就足够快了。
您可以使用子 shell 调用,其中 shell 不介意第一个命令通过信号终止,如:
set lastlog [exec -- bash -c "last -F | head -n 2 | tail -n 1"]
这样做的好处是可以在 "last" 发出其全部输出之前实际终止执行,如果输出很长,这很好。