Question

So I'm trying to get a list of all the directories i'm currently running a program in, so i can keep track of the numerous jobs i have running at the moment.

When i run the commands individually, they all seem to work, but when i chain them together, something is going wrong... (ll is just the regular ls -l alias)

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

enter image description here

Why is it that when i have the ll /proc/31353/fd inside the for loop, it cannot access the file, but when i use it normally it works fine?

And piped through 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
Was it helpful?

Solution

chepner had the right hunch. The output of top is designed for humans, not for parsing. The hexdump shows that top is producing some terminal escape sequences. These escape sequences are part of the first field of the line so the resulting file name is something like /proc/\e(B\e[m\e(B\e[m21353/pid instead of /proc/21353/pid where \e is an escape character.

Use ps, pgrep or pidof instead. Under Linux, you can use the -C option to ps to match an exact program name (repeat the option to allow multiple names). Use the -o option to control the display format.

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

If you want to sort by decreasing CPU usage:

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 

enter image description here

Additionally, use backticks instead of dollar-parenthesis for command substitution — quotes inside backticks behave somewhat bizarrely, and it's easy to make a mistake there. Quoting inside dollar-parenthesis is intuitive.

OTHER TIPS

try to use "cut" instead of "awk", something like this:

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
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top