shell script gives output in 2 lines I need only 1 - linux

I have the following commands saved in a .sh file
prog=$1
ps axf | grep $prog | grep -v grep | awk '{print "kill -9 " $1}'
I get the following output when I execute it
kill -9 3184
kill -9 20359
But I just need the first line of it as that is the only valid pid. How can I remove the 2nd line from the output.

There are a few issues with what you want to do:
You're building a chain of 4 commands for something relatively simple
You're going to get as a result only the first line of a list of processes containing $prog (excluding the grep $prog which you filtered out); how can you be sure that's the process you want?
The correct command to use is
pkill $prog`
as suggested in the comments, which probably will do what you want.
Just for information, and to answer your question, you can pipe an output to head -n 1 to return only the first line:
<list of commands> | head -n 1
However, in your case this would add a fifth command to the chain, so I recommend you don't do it this way.

Related

cat: pid.txt: No such file or directory

I have a problem with cat. I want to write script doing the same thing as ps -e. In pid.txt i have PID of running processes.
ls /proc/ | grep -o "[0-9]" | sort -h > pid.txt
Then i want use $line like a part of path to cmdline for evry PID.
cat pid.txt | while read line; do cat /proc/$line/cmdline; done
i try for loop too
for id in 'ls /proc/ | grep -o "[0-9]\+" | sort -h'; do
cat /proc/$id/cmdline;
done
Don't know what i'm doing wrong. Thanks in advance.
I think what you're after is this - there were a few flaws with all of your approaches (or did you really just want to look at process with a single-digit PID?):
for pid in $(ls /proc/ | grep -E '^[0-9]+$'|sort -h); do cat /proc/${pid}/cmdline; tr '\x00' '\n'; done
You seem to be in a different current directory when running cat pid.txt... command compared to when you ran your ls... command. Run both your commands on the same terminal window, or use absolute path, like /path/to/pid.txt
Other than your error, you might wanna remove -o from your grep command as it gives you 1 digit for a matching pid. For example, you get 2 when pid is 423. #Roadowl also pointed that already.

kill multiple process at once works only manually not from inside script

I'm trying to kill multiple process at the same time.
Im using this simple for loop to kill the process by PID number.
for i in $(ps -ejH | grep omn_bdxtrc|awk '{print $1}'); do kill ${i}; done
The loop works fine if I enter it manually in the terminal.
but if I want to us it from inside an file (*.sh) it returns this output.
/functions.sh: line 231: kill: 25211
25698
27930
8477
5018
16383
13488
2403
10963 18796: arguments must be process or job IDs
have tried multiple ways that works manually, but not from the file.
Any ideas why this is happening?
Thanks in advance.
It looks like the PIDs are being passed as a single argument delimited by line breaks, which kill does not seem to like.
I would simplify the approach by removing the loop completely and just passing the PIDs to kill via xargs:
ps -ejH | grep omn_bdxtrc | awk '{print $1}' | xargs kill
Alternatively (if you don't have or don't want to use xargs for some reason), you can keep your current loop and just sanitize the output from awk by changing all possible line breaks to spaces using tr:
for i in $(ps -ejH | grep omn_bdxtrc | awk '{print $1}' | tr '\n' ' '); do kill ${i}; done
But this is not that elegant.
Probably the most elegant solution would be to use killall, assuming you know the exact name of the process:
killall omn_bdxtrc
Or if you don't know the exact name and need to match a part of it:
killall --regexp '.*omn_bdxtrc.*'

grep from output and do something on first occurence

I have a stream of logs from a specific tool on my server with persistent output.
I've say it's like
task 3 done
all is ok
added another task
something made
I cannot grep from output file by a reason, but I have an opportunity of make something through pipes or output streams:
./myexecutablefile | grep something
In this case I receive highlighted "something" if it appeared in output.
I want to make something if first occurrence is met, but i don't know how, because of continuous stream. For example my goal is to kill process if I will see some error.
Surely this doesn't work, && kill will begin after executable ends
./myexecutable | grep 'Error occured' && kill -9 myexecutable
You need to use -q option in grep:
./myexecutable | grep -q 'Error occured' && kill -9 myexecutable
If you are interested in the first occurrence only, you can use the -m switch of grep:
./myexecutablefile | grep -m1 something && do_something
This will still output the matching line. To suppress that, you can turn on -q, but then, you don't need -m1 anymore:
./myexecutablefile | grep -q something && do_something

Shell script to kill process with highest PID

I would like to kill a specific java-process via a shell script.
I know that kill -9 $(pidof java) will kill it, yet it will also kill all other java processes. I know that the java-process I would like to kill is the one that was started as the last one.
So if I use pidof java, I will retrieve a set of PIDs, how can I assign that to a list (or sth similar) and the get the last element of it?
Thanks
I am kind of a newbie for Shell scripts, but here is my solution:
kill -9 `ps aux | grep [j]ava | awk '{ print $2 }' | sort -nr | head -n 1`
ps aux prints the current processes
grep [j]ava finds the processes containing "java" inside, except the current grep command
awk { print $2 } retrieves the second column of ps, which is the pid
sort -nr sorts the output by descending order (n is for numerical)
head -n 1 gets the first line of the sorted pids, which is the highest

How to grep both header and pattern with grep

I need to grep both header and also particular pattern only using grep,
eg
for command "ps"
output
PID TTY TIME CMD
10280 pts/16 00:00:00 ps
32463 pts/16 00:00:00 bash
how can i grep both header and pattern like 32463 so output should be
PID TTY TIME CMD
32463 pts/16 00:00:00 bash
And One thing is that solution should be general that means it should be applicable to all commands that have headers
Try this:
ps | head -1; ps | grep bash
Like this:
ps | ( read -r head; printf '%s\n' "$head"; grep bash )
This generalizes to other commands, such as
( read -r head; printf '%s\n' "$head"; sort -k4n ) <input.csv >input-sorted-4n.csv
You could encapsulate this into a script called keepheader:
#!/bin/sh
read -r head
printf '%s\n' "$head"
exec "$#"
Use like
ps | keepheader grep bash
keepheader sort -k4n <input.csv >input-sorted-4n.csv
or maybe even
keepheader keepheader grep foo <<HERE
Header with underlines
------ ---- ----------
Cat food Whiskas
Mouse bait Cheese
HERE
(Actually maybe make the script accept an optiinal numeric parameter to specify how many header lines to keep; I leave this as an exercise for the reader.)
I suggest sed:
sed -n "1p;/$pattern/p"
how can i grep both header and pattern
You could try this
ps | grep -e 'PID\|32463'
solution should be general that means it should be applicable to all commands that have headers
This requirement is almost impossible to satisfy by grep, because different commands have different headers, it is impossible to assign a regular expression to match all of them.
But you could use the following command to achieve your goal:
command | perl -e 'while(<STDIN>) { print if $. == 1 or m/$ARGV[0]/ }' pattern
If it is too cumbersome for daily use, you can put it in a custom script, such as my-grep, and put that script in your $PATH, then you can use that script like a normal command:
command | my-grep pattern
With out using grep you can get this output for ps option
$ps -p 32463
-p Select by PID.
This selects the processes whose process ID numbers appear in pidlist. Identical to p and --pid.

Resources