4

ps aux --sort=-%cpu | grep -v 'whoami' command is supposed to output processes that are not started by the effective user. However, it prints out my user's processes as well as other users'. Please explain what's wrong.

1
  • 2
    it looks like you have used 'whoami` which will result in it listing all those who aren't of username "whoami". i think you meant whoami (with backticks which this site tranforms to a command) which will be replaced with the result of $USER (ie. your username) and thus will exclude your username (it won't work anyway if for example your username was just a "r" - 'root' would also be excluded as it contains the "r".. a command within backtick is excuted & its result replaces the backslash-quoted bit..
    – guiverc
    Dec 7, 2017 at 1:32

2 Answers 2

7

grep -v 'whoami' excludes lines matching literal string whoami

If you want to exclude lines matching the output of the whoami command, you need to replace the single quotes with backticks

ps aux --sort=-%cpu | grep -vFe `whoami`

or use the $(...) form of command substitution instead

ps aux --sort=-%cpu | grep -vFe "$(whoami)"

Alternatively, you could skip the grep altogether by negating the user selection directly:

ps -Nu `whoami` --sort=-%cpu u
1
  • Any reason not to use the standard $USER variable here? Why launch a separate process?
    – terdon
    Dec 7, 2017 at 11:04
3

As steeldriver's answer already explained, your command is wrong because it filters against literal string whoami, and you could use grep -v "$(whoami)"; you could also use grep -v "$USER" to achieve desired effect.

Another, better way would be to let ps handle filtering with -Nu as steeldriver showed or top:

$ top -u '!root'  -n 1 

However, I would recommend you use actual login name - the literal string - as in grep -v 'myuser' for three reasons:

  1. It is possible to create a user with * character:

     $ sudo -p ">" useradd  -s /bin/bash -p "$(mkpasswd -m SHA-512 '123')" 'myuser1*'
     >
    
     $ su 'myuser1*'
     Password: 
     myuser1*@eagle:/home/xieerqi$ 
    

    Why is this important ? Because when you use $() without quoting, wildcard can become an issue with shell globbing if there exist files which may contain part of the username, then the command will break:

    myuser1*@eagle:/home/xieerqi$ ps aux | strace -e execve grep -v 
    $(whoami) > /dev/null
    execve("/bin/grep", ["grep", "-v", "myuser1.pdf", "myuser1.txt"], 
    [/* 82 vars */]) = 0
    +++ exited with 1 +++
    

    Notice how shell expanded myuser1* into myuser1.pdf and myuser1.txt, in accordance with shell globbing. Not what you expected, right ?

  2. Second reason - if you're logging into multiple usernames ( which some system administrators may do) or have multiple terminals open, you can get confused by whoami output:

    $ whoami
    root
    $ logname
    xieerqi
    

    If your intent is to filter out root processes, this will work, but if you're logged in as root yet want to filter out your admin user's processes - whoami will give you not the thing you intended.

  3. Environment variables can be unset:

    $ unset USER
    $ echo "empty $USER ?"
    empty  ?
    

So what did we learn from this ?

  • quote the variables !
  • know what you're actually logged in as and what your intent is
  • be careful with passing stuff to grep
  • try to make use of commands and their options whenever possible
7

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .