使用 bash 和 netstat 测试端口是否正在使用?

Testing whether or not a port is in use with bash and netstat?

我已经写了一个很长,而且相当复杂的 Bash 脚本,它使我能够非常容易地使用选定的选项启动我的节点服务器...问题是它不能正常工作。

给我带来麻烦的部分在这里...

if netstat -an | grep ":$REQUESTED_PORT" > /dev/null
then
    SERVICE_PIDS_STRING=`lsof -i tcp:$REQUESTED_PORT -t`
    OLD_IFS="$IFS"
    IFS='
    '
    read -a SERVICE_PIDS <<< "${SERVICE_PIDS_STRING}"
    IFS="$OLD_IFS"
    printf 'Port is in use by the following service(s)...\n\n-------------------\n\nProcess : PID\n\n'
    for PID in "${SERVICE_PIDS[@]}"
        do
            PROCESS_NAME=`ps -p $PID -o comm=`
            printf "$PROCESS_NAME : $PID\n"
        done
    printf "\n-------------------\n\nPlease kill the procceses utilizing port $REQUESTED_PORT and run this script again...exiting.\n"
    exit

此脚本的预期功能是使用netstat 测试请求的端口是否繁忙。如果是这样,它会报告使用该端口的 PID,以便用户可以根据需要杀死它们。

我相当确定这是我使用方式的问题 netstat。有时,netstat if 语句会触发,即使没有任何东西使用该端口。 lsof 工作正常,未报告任何使用该端口的 PID。

然而,当脚本最后一次出现这个错误时,我声明了 REQUESTED_PORT 然后 运行 netstat -an | grep ":$REQUESTED_PORT"。 shell 没有报告任何内容。

导致它在不适当的时间触发的这种情况有什么问题?

编辑

我还应该提到这台机器是 运行 Debian Jessie。

您正在搜索大量文本,而您想要的数字可能会出现在任何地方。最好缩小搜索范围;您可以在同一步骤中获取 PID 和进程名称。其他一些优化如下:

# upper case variable names should be reserved for the shell
if service_pids_string=$(lsof +c 15 -i tcp:$requested_port)
then
    # make an array with newline separated string containing spaces
    # note we're only setting IFS for this one command
    IFS=$'\n' read -r -d '' -a service_pids <<< "$service_pids_string"
    # remove the first element containing column headers
    service_pids=("${service_pids[@]:1}")
    printf 'Port is in use by the following service(s)...\n\n-------------------\n\nProcess : PID\n\n'
    for pid in "${service_pids[@]}"
    do
        # simple space-separated text to array
        pid=($pid)
        echo "${pid[0]} : ${pid[1]}"
    done
    # printf should be passed variables as parameters
    printf "\n-------------------\n\nPlease kill the procceses utilizing port %s and run this script again...exiting.\n" $requested_port
fi

你应该运行你的脚本通过shellcheck.net;它可能会发现我没有发现的其他潜在问题。