Назад | Перейти на главную страницу

Вывести последний столбец, содержащий пробелы и специальные символы

Мне нужен полный путь / команда, которая была выполнена для запуска процесса, который доступен в сети - прослушивает 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)

Что я здесь делаю не так?

Спасибо

Ошибка здесь: awk '$2 == '"$PID"

  • если $PID не является строго числовым, тогда вы выполняете проверку равенства для строки без кавычек, так что, действительно, кто знает, как awk интерпретирует ее?

    $ PID="3000)"
    $ echo hello | mawk '$2 == '"$PID"
    mawk: line 1: extra ')'
    

Передача переменной оболочки в awk как переменной awk (с -v option) проясняет это.

Очистив ваш код другими способами, у нас есть:

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]} буду работать
  • Вы можете удалить косую черту и все последующие символы с помощью расширения параметра оболочки, поэтому вам не понадобится awk для получения PID
  • вам не нужно перетаскивать awk в awk: консолидировать
  • передать переменную оболочки в awk с -v вариант

Не могли бы вы попробовать это:

for i in $(netstat -atnp | awk '{ print $7 }' | grep ^[0-9] | awk -F\/ '{ print $1 }'); do echo "PID: $i " $(ps faxuwwww | grep $i); done