2. Shell命令语言

2. Shell命令语言

当我把这个

nc -l 12345 >nc_out

在 shell 脚本中,运行它,然后使用 telnet 从其他 shell 进行连接,它允许我输入一些文本并将其结束数控输出

但是如果我在后台启动 nc (我想稍后从同一脚本启动 telnet):

nc -l 12345 >nc_out &

连接立即关闭:

# telnet localhost 12345
Trying ::1...
telnet: connect to address ::1: Connection refused
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Connection closed by foreign host
#

将 nc_out 文件留空。

这是为什么?如何才能让nc正常接受连接?


笔记:

  • 在 RHEL 和 Fedora 上,数控nmap-ncat这样做,但是 Debian 的NC-传统确实接受连接并让我将数据保存到 nc_out。

  • 如果我从相同的脚本或不同的(SSH)会话调用 telnet 并不重要,行为是相同的

  • 我还按照 @Hauke Laging 的建议使用 strace 运行了命令并发布了Pastebin 上的 strace 输出

答案1

在禁用作业控制的非交互式 shell 中执行的后台命令(就像 shell 脚本中的情况一样)会stdin/dev/null.

sh -c 'nc -l 12345 1>nc_out & lsof -p $!'

POSIX.1-2008:

2. Shell命令语言

[...]

异步列表

如果命令由控制运算符 ( '&' ) 终止,则 shell 应在子 shell 中异步执行该命令。这意味着 shell 在执行下一个命令之前不应等待命令完成。

在后台运行命令的格式为:

command1 & [command2 & ... ]

在执行任何显式重定向之前,异步列表的标准输入应被视为分配给具有相同属性的文件/dev/空。如果它是交互式 shell,则不需要发生这种情况。在所有情况下,标准输入的显式重定向应覆盖此活动。

当客户端通过 port建立与已经运行的命令telnet的连接时,后台命令似乎检测到其 stdin 上的 EOF 并启动其关闭过程,因为它被迫从 /dev/null 读取。命令 ( )的返回值为零表示文件结束。localhostnc12345ncreadman 2 read

# strace output (from http://pastebin.com/YZHW31ef)
14:32:26 read(0, "", 2048)              = 0
14:32:26 shutdown(4, 1 /* send */)      = 0

以下是一些保持telnet运行和通信的解决方案nc

sh -c 'nc -l 12345 0<&0 1>nc_out &'
sh -c 'nc -l 12345 0<&- 1>nc_out &'
sh -c 'tail -f /dev/null | nc -l 12345 1>nc_out &'
sh -c 'rm -f fifo; mkfifo fifo; exec 3<>fifo; nc -l 12345 0<fifo 1>nc_out &'

答案2

nc -ld host port >> logfile &

-d 不要尝试从标准输入读取。

这将在后台“nc”执行。
因为,当后台执行'nc'时,它会读取stdin stdout stderr。
如果不禁止读取标准输入,它将中止。

例子:

nc -ld 12345 > nc_out

nc 127.0.0.1 12345 
#enter something

数据存储在数控输出文件。

相关内容