‘ERROR: Garbage option.’ when using ps and awk

The other day I wanted to create a simple bash script that would receive the name of a process and print out its pid. I wanted to run ps and then use awk to filter out the correct process and print out its pid. So I created the following bash script (called getPIDOf):

#! /bin/bash

command=”ps -o pid,command -C $1″
for (( i=1; i<=$#; i+=1 )); do
curval=${!i}
command=”$command | grep \”$curval\””
done
command=”$command | awk ‘!/awk/ && !/getPIDOf/ {print \$1}'”

echo $command
$command

I was quite pleased with myself that I had even added in the option to specify multiple identifiers for the process. But when I ran the script I got the following output:

yuval@obt:$ ./getPIDOf nc
ps -o pid,command -C nc | grep “nc” | awk ‘!/awk/ && !/getPIDOf/ {print $1}’
ERROR: Garbage option.
********* simple selection *********  ********* selection by list *********
-A all processes                      -C by command name
-N negate selection                   -G by real group ID (supports names)
-a all w/ tty except session leaders  -U by real user ID (supports names)
-d all except session leaders         -g by session OR by effective group name
-e all processes                      -p by process ID
T  all processes on this terminal     -s processes in the sessions given
a  all w/ tty, including other users  -t by tty
g  OBSOLETE — DO NOT USE             -u by effective user ID (supports names)
r  only running processes             U  processes for specified users
x  processes w/o controlling ttys     t  by tty
*********** output format **********  *********** long options ***********
-o,o user-defined  -f full            –Group –User –pid –cols –ppid
-j,j job control   s  signal          –group –user –sid –rows –info
-O,O preloaded -o  v  virtual memory  –cumulative –format –deselect
-l,l long          u  user-oriented   –sort –tty –forest –version
-F   extra full    X  registers       –heading –no-heading –context
********* misc options *********
-V,V  show version      L  list format codes  f  ASCII art forest
-m,m,-L,-T,H  threads   S  children in sum    -y change -l format
-M,Z  security data     c  true command name  -c scheduling class
-w,w  wide output       n  numeric WCHAN,UID  -H process hierarchy

I thought that I must have something wrong with the escaping. But when I ran the command that was printed out, it worked fine:

yuval@obt:$ ps -o pid,command -C nc | grep “nc” | awk ‘!/awk/ && !/getPIDOf/ {print $1}’
892

I even tried the following simplified script:

#! /bin/bash

command=”ps -o pid,command -C $1″
command2=”awk ‘!/awk/ && !/getPIDOf/ {print \$1}'”

echo “$command | $command2”
$command | $command2

And got the following output:

yuval@obt:$ ./getPIDOf nc
ps -o pid,command -C nc | awk ‘!/awk/ && !/getPIDOf/ {print $1}’
awk: 1: unexpected character ”’

By this time I was quite puzzled. My simple getPIDOf script had become full of strange behaviors. So I decided to take the quick route out and use Perl instead of awk.

Here is my final version of the getPIDOf script:

#!/usr/bin/perl -w
use strict;

die “Usage: $0 <identifier1> [identifier2] …\n” unless (@ARGV);

my $command = “/bin/ps -o pid,command -C \”$ARGV[0]\””;
my $output = `$command`;
foreach my $line (split(/\n/, $output))
{
if ($line =~ /^\s*(\d+)\s+(.+?)$/)
{
my $pid = $1;
my $command = $2;
my $found_mismatch = 0;
foreach my $filter (@ARGV)
{
if ($command !~ /$filter/)
{
$found_mismatch = 1;
last;
}
}

if ($found_mismatch){next;
}

print “$pid\n”;
}
}

And the output, as desired, is:

yuval@obt:$ ./getPIDOf nc
892

This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *