Bash:如何在连接关闭之前使telnet或nc在后台工作

时间:2016-07-07 13:04:49

标签: bash telnet netcat

下面我描述了我正在努力解决的问题以及我目前的决定。 请指出更聪明/更小的决定,也很乐意收到反馈

因此,本地主机上有一个发布者和一个客户端,它们通过端口8080进行通信。我可以telnet或者nc到这个端口并正常地将输出写入日志,但不能使相同的命令在后台运行。

我看到的是,当它们在后台启动时,它们会在获得第一个输入后立即停止( 它真的如此吗? ),但在前景中它们可以正常工作发布商在此端口关闭连接后才会死亡。

这是正常情况:

> telnet localhost 8080 | tee output.log (or >>output.log, no matter)
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.

Publisher开始通过端口发送信息。

***some necessary output***

Publisher关闭端口。

Connection closed by foreign host.

但是当它在后台启动时会立即停止,无需等待输出:

> nohup telnet localhost 8080 | tee output.log (or <command> &, or nohup <command> &)
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Connection closed by foreign host.

2 个答案:

答案 0 :(得分:2)

您改为使用netcat命令:

nohup nc -d localhost 8080 >>console-8080.txt &

如果要使用日期缩进日志文件:

nohup nc -d localhost 8080 | while read line ; do echo `date +'%d%m%Y-%H%M%S'`: $line >>console-8080.txt; done &

要在关闭时重新启动nc进程:

#!/bin/bash
ip=$1
port=$2
while [ 1 ]
do
    nc -d $ip $port | while read line ; do echo `date +'%d%m%Y-%H%M%S'`: $line >>console-$ip-$port.txt; done
    sleep .1
done

答案 1 :(得分:1)

这是我要来的期望剧本。它正在后台推出。

nohup ./telnet_expect.sh &

该脚本生成新的bash会话并执行通常的文件重定向。

通常我会安排bash之间的通信和期望通过env变量,这里我没有实现它,因为整个用例足够小。

#!/bin/bash

echo -e "\n$(date +%Y-%m-%d_%H:%M:%S,%3N) -- Started telnet_expect.sh\n"

logFile="/export/home/<user>/<folder>/output.log"
logFileExpect="/export/home/<user>/<folder>/expect.log"

echo > "$logFile"
echo > "$logFileExpect"

until nc -w 1 localhost 8080
do
    sleep 1
done

expect -c "
log_user 1
set timeout 250

proc err_exit {msg} {
        puts \"---\"
    puts stderr \"\$msg\"
        send \"exit status: \$?\r\"
    exit 1
}

exp_internal -f /export/home/<user>/<folder>/expect.log 1

spawn bash

send \"telnet localhost 8080 >> /export/home/<user>/<folder>/output.log\r\"
sleep 10
expect {
    \"*onnection closed by foreign host*\" {
        send \"echo Success\r\"
    }
    timeout {
        err_exit \"\nError: timeout\n\"
    }
}

send \"exit\r\"

expect eof
"

echo -e "\n$(date +%Y-%m-%d_%H:%M:%S,%3N) -- Finished telnet_expect.sh\n"

Upd:下面是更具可配置性的版本,它将日志文件作为参数。这是如何推出:

nohup ./telnet_expect.sh <your_output_log_file> &

此处的IP和端口值仅定义一次,因此很容易将它们移动到参数中。还有调试日志和控制台日志,以了解究竟发生了什么。用户可以提供日志文件的绝对或相对路径。

#!/bin/bash

scriptFolderPath=$(dirname $(readlink -f "$0"))
logDir="$scriptFolderPath"
logFileDefault="$logDir"/"output_default.log"
logFileExpect="$logDir"/"expect.log"
ip="localhost"
port="8080"

logConsole="$logDir"/"console_telnet.log"
echo > "$logConsole"

echo -e "\n$(date +%Y-%m-%d_%H:%M:%S,%3N) -- Started telnet_expect.sh\n" >> "$logConsole"

### debug info
logDebug="$logDir"/"debug_telnet.log"
echo > "$logDebug"
exec 5> "$logDebug"
BASH_XTRACEFD="5"
PS4='$LINENO: '
set -x

if [ -z "$1" ]; then
    logFile="$logFileDefault"
else
    if [[ $logFile =~ "/" ]]; then
        logFile="$1"
    else
        echo "Got the log file in the same folder as the script" >> "$logConsole"
        logFile="$scriptFolderPath"/"$1"
    fi
fi

echo > "$logFile"
echo > "$logFileExpect"

### setting envs
echo -e "\nsetting BCKGR_TELNET_LOG" >> "$logConsole"
export BCKGR_TELNET_LOG="$logFile"
echo "set BCKGR_TELNET_LOG: $BCKGR_TELNET_LOG" >> "$logConsole"

echo -e "\nsetting BCKGR_TELNET_LOG_EXPECT" >> "$logConsole"
export BCKGR_TELNET_LOG_EXPECT="$logFileExpect"
echo -e "set BCKGR_TELNET_LOG_EXPECT: $BCKGR_TELNET_LOG_EXPECT\n" >> "$logConsole"

echo -e "\nsetting BCKGR_TELNET_LOG_PORT" >> "$logConsole"
export BCKGR_TELNET_LOG_PORT="$port"
echo -e "set BCKGR_TELNET_LOG_PORT: $BCKGR_TELNET_LOG_PORT\n" >> "$logConsole"

echo -e "\nsetting BCKGR_TELNET_LOG_IP" >> "$logConsole"
export BCKGR_TELNET_LOG_IP="$ip"
echo -e "set BCKGR_TELNET_LOG_IP: $BCKGR_TELNET_LOG_IP\n" >> "$logConsole"

until nc -w 1 "$ip" "$port"
do
    sleep 1
done

expect -c "
log_user 1
set timeout 250

proc err_exit {msg} {
        puts \"---\"
    puts stderr \"\$msg\"
        send \"exit status: \$?\r\"
    exit 1
}

puts \"Reading BCKGR_TELNET_LOG_EXPECT\"

if {[info exists env(BCKGR_TELNET_LOG_EXPECT)]} {
    set bckgr_telnet_log_expect $::env(BCKGR_TELNET_LOG_EXPECT)
        puts \"Found BCKGR_TELNET_LOG_EXPECT\"
} else {
        err_exit \"Error while reading env variable BCKGR_TELNET_LOG_EXPECT\"
}

puts \"Reading BCKGR_TELNET_LOG\"

if {[info exists env(BCKGR_TELNET_LOG)]} {
    set bckgr_telnet_log $::env(BCKGR_TELNET_LOG)
        puts \"Found BCKGR_TELNET_LOG\"
} else {
        err_exit \"Error while reading env variable BCKGR_TELNET_LOG\"
}

puts \"Reading BCKGR_TELNET_LOG_PORT\"

if {[info exists env(BCKGR_TELNET_LOG_PORT)]} {
    set bckgr_telnet_log_port $::env(BCKGR_TELNET_LOG_PORT)
        puts \"Found BCKGR_TELNET_LOG_PORT\"
} else {
        err_exit \"Error while reading env variable BCKGR_TELNET_LOG_PORT\"
}

puts \"Reading BCKGR_TELNET_LOG_IP\"

if {[info exists env(BCKGR_TELNET_LOG_IP)]} {
    set bckgr_telnet_log_ip $::env(BCKGR_TELNET_LOG_IP)
        puts \"Found BCKGR_TELNET_LOG_IP\"
} else {
        err_exit \"Error while reading env variable BCKGR_TELNET_LOG_IP\"
}

exp_internal -f \$bckgr_telnet_log_expect 1

spawn bash

send \"telnet \$bckgr_telnet_log_ip \$bckgr_telnet_log_port >> \$bckgr_telnet_log\r\"
sleep 10
expect {
    \"*onnection closed by foreign host*\" {
        send \"echo Success\r\"
    }
    timeout {
        err_exit \"\nError: timeout\n\"
    }
}

send \"exit\r\"

expect eof
"

echo -e "\nUnsetting env variables" >> "$logConsole"
unset BCKGR_TELNET_LOG
unset BCKGR_TELNET_LOG_EXPECT
unset BCKGR_TELNET_LOG_PORT
unset BCKGR_TELNET_LOG_IP

echo -e "\n$(date +%Y-%m-%d_%H:%M:%S,%3N) -- Finished telnet_expect.sh\n" >> "$logConsole"