Странное поведение Баша


Таким образом, я пытаюсь получить список всех каталогов, в которых я в настоящее время запускаю программу, чтобы я мог отслеживать многочисленные задания, которые я выполняю в данный момент.

Когда я выполняю команды по отдельности, все они, кажется, работают, но когда я связываю их вместе, что-то идет не так... (ll - это просто обычный ls -l псевдоним)
for pid in `top -n 1 -u will | grep -iP "(programs|to|match)" | awk '{print $1}'`; 
    do 
    ll /proc/$pid/fd | head -n 2 | tail -n 1; 
done

Введите описание изображения здесь

Почему, когда у меня есть ll /proc/31353/fd внутри цикла for, он не может получить доступ к файлу, но когда я использую его нормально, он работает хорошо?

И пропущено через hexdump -C:

$ top -n 1 -u will | 
    grep -iP "(scatci|congen|denprop|swmol3|sword|swedmos|swtrmo)" | 
        awk '{print $1}' | hexdump -C
00000000  1b 28 42 1b 5b 6d 1b 28  42 1b 5b 6d 32 31 33 35  |.(B.[m.(B.[m2135|
00000010  33 0a 1b 28 42 1b 5b 6d  1b 28 42 1b 5b 6d 32 39  |3..(B.[m.(B.[m29|
00000020  33 33 31 0a 1b 28 42 1b  5b 6d 1b 28 42 1b 5b 6d  |331..(B.[m.(B.[m|
00000030  33 30 39 39 36 0a 1b 28  42 1b 5b 6d 1b 28 42 1b  |30996..(B.[m.(B.|
00000040  5b 6d 32 36 37 31 38 0a                           |[m26718.|
00000048
2 3

2 ответа:

У Чепнера было верное предчувствие . Вывод top предназначен для людей, а не для разбора. В шестнадцатеричного представления показывает, что ведущие дают побег последовательностей. Эти escape-последовательности являются частью первого поля строки, поэтому результирующее имя файла-это что-то вроде /proc/\e(B\e[m\e(B\e[m21353/pid вместо /proc/21353/pid, где \e - это escape-символ.

Использование ps, pgrep или pidof вместо этого. В Linux вы можете использовать опцию -C для ps, чтобы соответствовать точному имени программы (повторите эту опцию разрешить несколько имен). Используйте опцию -o для управления форматом отображения.

for pid in $(ps -o pid= -C scatci -C congen -C denprop -C swmol3 -C sword -C swedmos -C swtrmo); do 
  ls -l /proc/$pid/fd | head -n 2 | tail -n 1
done

Если вы хотите сортировать по уменьшению использования процессора:

for pid in $(ps -o %cpu=,pid= \
                -C scatci -C congen -C denprop -C swmol3 -C sword -C swedmos -C swtrmo |
             sort -k 1gr |
             awk '{print $2}'); do 

Введите описание изображения здесь

Кроме того, используйте backticks вместо Dollar-parenthesis для замены команд-кавычки внутри backticks ведут себя несколько странно, и там легко ошибиться. Цитирование внутри долларовой скобки интуитивно.

Попробуйте использовать " cut "вместо " awk", что-то вроде этого:

for pid in `top -n 1 -u will | grep -iP "(scatci|congen|denprop|swmol3|sword|swedmos|swtrmo)" | sed 's/  / /g' | cut -d ' ' -f2`; do echo /proc/$pid/fd | head -n 2 | tail -n 1; done