当我把这个
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 $!'
2. Shell命令语言
[...]
异步列表
如果命令由控制运算符 ( '&' ) 终止,则 shell 应在子 shell 中异步执行该命令。这意味着 shell 在执行下一个命令之前不应等待命令完成。
在后台运行命令的格式为:
command1 & [command2 & ... ]
在执行任何显式重定向之前,异步列表的标准输入应被视为分配给具有相同属性的文件/dev/空。如果它是交互式 shell,则不需要发生这种情况。在所有情况下,标准输入的显式重定向应覆盖此活动。
当客户端通过 port建立与已经运行的命令telnet
的连接时,后台命令似乎检测到其 stdin 上的 EOF 并启动其关闭过程,因为它被迫从 /dev/null 读取。命令 ( )的返回值为零表示文件结束。localhost
nc
12345
nc
read
man 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
数据存储在数控输出文件。