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.

  • 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 '17 at 1:32
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
  • Any reason not to use the standard $USER variable here? Why launch a separate process? – terdon Dec 7 '17 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

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.