Something is wrong with unix script - bash

Following is my script, every time I run this it goes into else part. when I run the TEST2EVAL command it gives me 1
#!/bin/sh
TEST2EVAL='ps auxf | grep some.jar | grep -v grep | wc -l'
if [ "$TEST2EVAL" = 1 ]
then
java -jar /path/to/jar &
else
echo "Running"
fi

Assuming you are trying to find out if any processes are running with some.jar on their command lines you probably want:
if pgrep -f some.jar; then
echo running;
else
echo not running;
fi

In in order save the output of a command in a variable, you have to enclose the command in backticks (`), not single quotes ('). Thus, change the second line of your script to:
TEST2EVAL=`ps auxf | grep some.jar | grep -v grep | wc -l`

You are using the wrong quotes for command substitution: not single quotes:
TEST2EVAL='ps auxf | grep some.jar | grep -v grep | wc -l'
but backquotes:
TEST2EVAL=`ps auxf | grep some.jar | grep -v grep | wc -l`
Better yet, use TEST2EVAL=$(ps auxf | grep some.jar | grep -v grep | wc -l) instead. It's much clearer, supported by all POSIX-compatible shells, and can be nested more easily when necessary.

Related

ps pipe and grep shell scripting illegal argument

New to shell scripting and just writing a little script to check if a process is running, if I use
PROCESS_NUM="ps -ef | grep '$1' | grep -v 'grep' | wc -l"
I get a "ps: illegal argument: |" error although if I echo out PROCESS_NUM and ctrl paste in the line it works just fine manually. Not sure why the | pipe is being troublesome here. Any help is much appreciated!
If you are trying to assig the output of ps -ef | grep '$1' | grep -v 'grep' | wc -l command to PROCESS_NUM variable, you need to use below:
PROCESS_NUM=`ps -ef | grep '$1' | grep -v 'grep' | wc -l`
or
PROCESS_NUM=$(ps -ef | grep '$1' | grep -v 'grep' | wc -l)
Using "", will treat the value inside of it as a string, except for some special character

Check if service is running prior to install using Puppet

I need to check if a service is already running before it installed using puppet.
My code is as following, but it is keep failing.
exec { 'bud_sh':
cwd => '/working_dir/',
command => "Some Command",
path => '/usr/bin:/usr/sbin:/bin:/usr/local/bin',
provider => 'shell',
onlyif => "test -f /path/to/shell/script/exist",
unless => "`ps -eaf | grep service | grep -v grep | wc -l` -eq 3"
}
Following is the Error Message.
Could not evaluate: /bin/sh: 3: command not found
Appreciate your time and consideration on this matter.
This error message ...
Could not evaluate: /bin/sh: 3: command not found
indicates that the shell tried to execute '3' as a command, and, unsurprisingly, did not find it. The only plausible source of such an issue in the code you presented is your Exec's unless command:
unless => "`ps -eaf | grep service | grep -v grep | wc -l` -eq 3"
When the command there is executed by the shell, it first executes
ps -eaf | grep service | grep -v grep | wc -l
in a subshell and captures its standard output. That output is slightly cleaned up, and then substituted into the overall command to yield, apparently,
3 -eq 3
, which the shell then tries to execute as the command '3', with two arguments. To instead evaluate that as a conditional expression, you need to present it as arguments to test or [ or similar:
unless => "test `ps -eaf | grep service | grep -v grep | wc -l` -eq 3"
unless => "ps -eaf | grep service | grep -v grep | wc -l -eq 3"
Other issues aside, you have a syntax error: -eq 3 is not a valid command. If you want to evaluate the output of a shell command in sh, you need to use a test construct. For example:
unless => '[ "$(ps -eaf | grep service | grep -v grep | wc -l)" -eq 3 ]'
On a broader level, the unless statement is looking for a truthy Boolean value. The test construct does that by providing its exit status. Write your statements with that in mind.

Killing parent process only, not both child and parent in bash

I'm trying to kill process by name. It's supposed to kill children processes first then the parent later but I only get parent killed. Help needed please. EDIT: SOLVED
Please try it this way:
PID=$(ps -aef | grep `whoami` | grep $argument | grep -v grep | grep -v $$ | awk '{print $2}'
for x in ${PID[#]}; do
CPID=$(ps -aef | grep `whoami` | grep $PID | grep -v grep | grep -v $$ | awk '{print $3}'
for y in ${CPID[#]}; do
kill $y
done
kill $x
done

simple bash script not terminating

I have very simple bash script:
#!/bin/bash
echo -n "A: ";
grep -v ">" | grep -o "A" $1 | wc -l;
I type
./script.sh 1.fasta
I got
A: 131
But the curcor is still blicking and my script is not finishing. What's wrong here?
Thank you.
This is the problem command:
grep -v ">" | grep -o "A" $1 | wc -l;
Since first command grep -v ">" is waiting for the input from STDIN as you haven't supplied any file to be searched by grep.
PS: Even grep -o "A" $1 is also problem since piped command will take input from output of the previous command in chain.
Probably you meant:
grep -v ">" "$1" | grep -o "A" | wc -l
Your first grep does not have a file argument so it will read from standard input:
grep -v ">" | grep -o "A" $1 | wc -l;
(read stdin) (read $1)
The reason why you get the 131 is because your second grep does have a file argument so it's getting all lines in $1 that have an A. However it's still waiting around for the end of the first grep to finish (which you can do with CTRL-D).
What you probably wanted to do is this:
grep -v ">" "$1" | grep -o "A" | wc -l
This will find all lines in $1 without a >, then all occurrences of A in that, counting them.

Count the number of processes and kill them

I am writing a script to kill all instances of the same process. As it is going to be used on Linux, AIX, HP-UX and Solaris, I need to use only built-in bash (sh) functions. That's why killall, pkill, etc. don't work for me.
Once there is only one instance of a process it should be just killed in traditional way:
kill -TERM `ps -ef | grep -v grep | grep $process | awk '{print $2}'`
However sometimes the program has extra instances running and that's why ps -ef | … returns more than one PID. That needs to be reported.
example:
bash-3.2$ ps -ef | grep -v grep | grep perl | awk '{print $2}'
5267
5268
5269
5270
5271
My thought was to store those values in a temporary variable and then send kill signal to each in a for loop.
bash-3.2$ tmp=`ps -ef | grep -v grep | grep perl | awk '{print $2}'`
bash-3.2$ echo $tmp
5267 5268 5269 5270 5271
However I still need the information if such a case occurred (how many instances were present).
It seems I need to check the whole string stored in the tmp variable and maybe count spaces?
Anyway the questions reduces to how to check how many values the $tmp variable stores?
For maximum portability and reliability, use -A (POSIX synonym of -e) and a custom format with -o rather than -f.
Your filtering of the output of ps is brittle: it may match other processes. You've had to exclude the grep process, and you may need to exclude your script as well, and there may be other completely innocent processes caught in the fray (such as your script itself) because their command line happens to contain $process as a substring. Make your filtering as strict as possible. With ps -o pid= -o comm=, you get just two columns (PID and command without arguments) with no header.
You don't need to use a loop to do the killing, kill accepts multiple arguments. For the counting, let the shell do it: you have a whitespace-separated list of numbers, to let the shell do the word splitting (with $(…) outside quotes) and count the number of resulting words ($#).
count_and_kill_processes () {
set -- $(ps -A -o pid= -o comm= |
awk -v "name=$process" '$2 == name {print $1}')
count=$#
if [ $# -ne 0 ]; then kill "$#"; fi
}
count_and_kill_processes foo
# now the number of killed processes is in $count
If your shell is bash or ksh on all machines, you can use an array.
pids=($(ps -A -o pid= -o comm= |
awk -v "name=$process" '$2 == name {print $1}') )
if [[ $# -ne 0 ]]; then kill "$#"; fi
# the number of killed processes is ${#pids}
use xargs:
ps aux | grep -ie perl | awk '{print $2}' | xargs kill -9
You can use a loop which should work in both cases:
for pid in $(ps -ef | grep -v grep | grep $process | awk '{print $2}'); do
echo $pid
done
Or count the number of matches:
if [ $(ps -ef | grep -v grep | grep $process | awk '{print $2}' | wc -l) -gt 1 ]
then
# more than one
fi

Resources