I wrote a piece of script similar to something below:

srvc_location=`ps -ef| grep '${sandbox}.*pset' | head 1 | awk {print $9}`
echo "SERVICE LOC : "$srvc_location

But strangely this $srvc_location is getting resolved most of the time, but sometimes its not getting resolved with this message:

SERVICE LOC : strrosdev_silo1_int.*pset

Some additional info:

  1. The above piece of code runs in a loop so everytime $sandbox has a new value.

  2. I tried with grep -e "${sandbox}.*pset but it didn't solve the issue.

  3. I can solve the problem with having two grep, grep $sandbox |grep pset, but I wanted to use just one with a pattern.

Why is it behaving like this?

  • The best method for you to debug this is to save the output from ps so you can see input and output, then it should become clear. Just a guess, maybe it finds the grep command from the ps listing and not the sandbox you want ? Find a script that uses grep, but avoids finding the searching grep process itself, then incorporate that into your script. – X Tian Sep 24 '15 at 10:13
  • Welcome to U&L. Please be so polite to read and apply help→tour. Post her get answered even if you don't put in question irrelevant begging ("Please help me"), so leave that out of future posts. Including a question, in the post, with a question mark makes it much more clear what you actually want to achieve, but can't. – Anthon Sep 24 '15 at 10:26

One reason your code is failing is that you are using single quotes '...' instead of double quotes "..." in your grep expression that surrounds the variable.

Use this instead

srvc_location=$(ps -ef| grep "${sandbox}.*pset" | head -1 | awk '{print $9}')
echo "SERVICE LOC : $srvc_location"

Actually, there is rarely any need to combine head, and awk like this, as awk can do itself:

srvc_location=$(ps -ef| grep "$sandbox.*pset" | awk '{print $9; exit}')

or even this, which is less clear but merges in the grep too:

srvc_location=$(ps -ef| awk -v sb="$sandbox" 'BEGIN { re = sb ".*pset" } $0 ~ re { print $9; exit}')

Here we have used several features of awk. We define an awk variable called sb that takes the value of the shell variable $sandbox. The BEGIN block defines an awk variable that contains the pattern we need to match, and the remainder of the scriptlet matches the Regular Expression within the awk variable re and prints the desired field, exiting immediately it has done so.

  • changing single quote to double quote is giving me the same response....Also just to clarify more, as per what I read on QUOTES... placing double quote will not resolve the value and take it the way it is(as a string), but single quotes resolve it to a variable – NishantM Sep 24 '15 at 11:44
  • @NishantM please can you provide an example of the value for $sandbox. Single quotes treat a string as literals. Double quotes interpolate the value of variables. So if a="one", then echo "is $a" and echo 'is $a' will print is one and is $a respectively. – roaima Sep 24 '15 at 16:45
  • $sandbox will take value like apsia_silo1_int, apsia_silo2_int, apsia_silo3_int,etc.. To Clarify as exactly what i wish to do... There are many sandboxes in my server and each of this sandbox has many process running under them... through 'ps' i want to take all the process in the server and filter out for individual sandbox's processes as per $sandbox value provided through a loop – NishantM Sep 24 '15 at 19:44
  • @NishantM so if this code doesn't work for you, what does it do that you don't expect? – roaima Sep 24 '15 at 20:16
  • Script does work as expected for almost evertime. But while running in loop sometime it is not able to resolve $srvc_location value. And to my surprise it happens for random value of $sandbox. So there is something command with my command srvc_location=ps -ef| grep '${sandbox}.*pset' | head 1 | awk {print $9} ... Although as per later answer '${sandbox}.*pse[t]' is solving my problem. But i am still to understand the reason for the failure – NishantM Sep 26 '15 at 6:42

grep must be greping itself.

you can try

srvc_location=$(ps -ef| grep ${sandbox}."*pse[t]" | awk '{print $9;exit;}')
  • grep "*pse[t]" will grep pset, but not pse[t]

    pse[t] as a regular expression (know as RE) means the string pse , then any caracter among t, the [] syntax is seldom use for one carcater, as it is indeed easiest to just mention t, general use is grep [abc]oo who match aoo, boo and coo.

    When you grep with a fixed string the result of a ps, you also grep the grep process and its arguments. In the trick above, the RE pse[t] evaluate to pset and doesn't match the fixed string pse[t].

edit: code golf

srvc_location=$(ps -ef| grep -m 1 -o ${sandbox}."*pse[t]")
  • -m 1 print only one matching pattern
  • -o only output matchint pattern
  • Thax alot !! it seems to work for me.. the code is not failing . But can you clarify what does "grep must be greping itself" mean? HOW putting [t] makes it overcome the issue? – NishantM Sep 24 '15 at 12:19

The command is better written as

srvc_location=$(ps -ef| grep '${sandbox}.*pset' | head 1 | awk {print $9})

Your version will set srvc_location to value ps and then tries to execute -ef and tries to pipe it's output to grep etc.


Just one thing to add to the numerous answers so far:

The command

head 1

Will output the first 10 lines of the file named 1, and will totally ignore stdin.

What you want (for that portion of your command) is:

head -1

which will output the first line (only one line) from stdin.

Or, of course, just use awk features as suggested already. But when you use head for anything, you should know this.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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