Different Results Between Ps Aux and 'Ps Aux' Inside a Script

Different results between ps aux and `ps aux` inside a script


Why can a single bash script show up multiple times in ps?

This is typical when any constructs which implicitly create a subshell are in play. For instance, in bash:

echo foo | bar

...creates a new forked copy of the shell to run the echo, with its own ps instance. Similarly:

( bar; echo done )

...creates a new subshell, has that subshell run the external command bar, and then has the subshell perform the echo.

Similarly:

foo=$(bar)

...creates a subshell for the command substitution, runs bar in there (potentially exec'ing the command and consuming the subshell, but this is not guaranteed), and reads its output into the parent.

Now, how does this answer your question? Because

result=$(ps aux | grep | wc)

...runs that ps command in a subshell, which itself creates an extra bash instance.


How can I properly ensure that only one copy of my script is running?

Use a lockfile.

See for instance:

  • How to prevent a script from running simultaneously?
  • What is the best way to ensure only one instance of a Bash script is running?

Note that I strongly suggest use of a flock-based variant.

Ps aux: shows the same script multiple times

Is anything in the while loop running in the background? It is conceivable that it has the same name as the parent process.

You can check whether some of the processes are subprocesses by running ps wafux and looking at the process tree.

If they are not "related" to each other, you have very likely simply run the script more than once, and the other processes are not finished yet.

Why if $(ps aux | grep ...) always succeeds in Bash?

Because the grep process itself is being returned by ps. You can "trick" grep to not match itself by surrounding one of the search characters in a character class [ ] which doesn't change the functionality:
Just do:

if ps aux | grep -q "[b]la bla" ; then echo "found" ; fi

Also, the use of process substitution $() is unnecessary. The if will work on the success of the last command in the pipe chain, which is what you want.

Note: The reason the character class trick works is because the ps output still has the character class brackets but when grep is processing the search string, it uses the brackets as syntax rather than a fixed string to match.

More elegant ps aux | grep -v grep

The usual technique is this:

ps aux | egrep '[t]erminal'

This will match lines containing terminal, which egrep '[t]erminal' does not! It also works on many flavours of Unix.

BASH pass a variable to grep produce different result

In your script:

  • You nowhere assign the variable "$n", thus it is empty. Probably you mean to use n=$2 or just use $2 positional variable instead
  • "task.log" is useless, if you want it use tee to pipe to it
  • Doing ps -axu and then limiting columns with awk looks strange. ps can format the output by itself
  • Parsing ps | grep is bad, use pgrep for that
  • remember to quote the variables

Your script after some fixing may look like this:

while true; do
cpuusage=$(
pgrep "$2" |
tee >(xargs ps -aux >task.log) |
xargs ps -o cpu% |
awk '{sum += $1} END {print sum}'
)
echo "Total CPU Usage: $cpuusage" >> monitor2.log
sleep "$1"
done
  • pgrep is a better alternative to ps -aux | grep ...
  • xargs passes pgrep outupt to ps -o %cpu=
  • ps -o %cpu= prints percent cpu usage for each process
  • awk is used to sum it.
  • Then a simple echo appends to monitor2.log file.

Viewing full output of PS command

It is likely that you're using a pager such as less or most since the output of ps aux is longer than a screenful. If so, the following options will cause (or force) long lines to wrap instead of being truncated.

ps aux | less -+S

ps aux | most -w

If you use either of the following commands, lines won't be wrapped but you can use your arrow keys or other movement keys to scroll left and right.

ps aux | less -S    # use arrow keys, or Esc-( and Esc-), or Alt-( and Alt-) 

ps aux | most # use arrow keys, or < and > (Tab can also be used to scroll right)

Lines are always wrapped for more and pg.

When ps aux is used in a pipe, the w option is unnecessary since ps only uses screen width when output is to the terminal.



Related Topics



Leave a reply



Submit