使用 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;它可能会发现我没有发现的其他潜在问题。
我已经写了一个很长,而且相当复杂的 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;它可能会发现我没有发现的其他潜在问题。