我需要一个完整的路径/命令来启动一个暴露在网络上的进程 - 监听 tcp/udp 。我确实设法使用下面的“一行代码”获得了所有这些:
netstat -nlp46|tail -n +3 | while IFS=" " read -r -a line;
do nb=${#line[@]};
PID=$(echo ${line[$((nb - 1))]} | awk -F'/' '{print $1}');
CMD=$(ps -ef|awk '$2 == '"$PID" |awk -F" " '{out=$8; for(i=9;i<=NF;i++){out=out""$i}; print out}');
echo $PID^$CMD;
done
但是当进程在命令行中包含一些特殊字符时,例如瘦服务器,脚本会出现以下错误
awk: line 1: missing ) near end of line
当我针对该进程运行部分脚本时,没有遇到任何问题
root@ftp-host02:~# PID=15000; COMMAND=$(ps -ef|awk '$2 == '"$PID" |awk '{out=$8; for(i=9;i<=NF;i++){out=out" "$i}; print out}');
echo $COMMAND
thin server (0.0.0.0:3000)
我在这里做错了什么?
谢谢
答案1
错误在这里:awk '$2 == '"$PID"
如果
$PID
不是严格的数字,那么您正在对未加引号的字符串进行相等性检查,因此实际上,谁知道 awk 将如何解释它?$ PID="3000)" $ echo hello | mawk '$2 == '"$PID" mawk: line 1: extra ')'
将 shell 变量作为 awk 变量传递给 awk(带有选项-v
)可以解决该问题。
通过其他方式清理代码,我们有:
netstat -nlp46 |
tail -n +3 |
while IFS=" " read -r -a fields; do
nb=${#fields[@]}
PID=${fields[nb-1]%%/*}
CMD=$( ps -ef | awk -v pid="$PID" '$2 == pid {out=$8; for(i=9;i<=NF;i++){out=out $i}; print out}' );
echo "$PID^$CMD";
done
笔记:
- 适当的缩进对于代码的可读性有很大帮助
- 数字索引数组的索引已在算术上下文中求值,因此
${ary[n-1]}
可以工作 - 您可以使用 shell 参数扩展删除斜杠及其后续字符,因此不需要 awk 来获取 PID
- 你不需要将 awk 连接到 awk:consolidate
-v
使用选项将 shell 变量传递到 awk
答案2
你可以尝试一下:
for i in $(netstat -atnp | awk '{ print $7 }' | grep ^[0-9] | awk -F\/ '{ print $1 }'); do echo "PID: $i " $(ps faxuwwww | grep $i); done