Linux bash script that kills a process (not started by me) after x amount of time - linux

I'm pretty inexperienced with Linux bash. That being said, I have a CentOS7 machine that runs a COTS application server. This application server runs other processes that sometimes hang. Since I have no control over the start of these processes, I'm looking for a script that runs every 2 minutes that kills processes of the name "spicer" that have been running for longer than 10 minutes. I've looked around and have only been able to find answers for processes that are run and owned by me.
I use the command ps -eo pid, command,etime | grep spicer to get all the spicer processes. The output of this command looks like:
18216 spicer -l/opt/otmm-10.5/Spi 14:20
18415 spicer -l/opt/otmm-10.5/Spi 11:49
etc...
18588 grep --color=auto spicer
I don't know if there's a way to parse this directly in bash. I'm also not well-versed at all in other Linux tools. I know that awk (or gawk) could possibly help.
EDIT
I have no control over the data that the process is working on.

What about wrapping the executable of spicer and start it using the timeout command? Let's say it is installed in /usr/bin/spicer. Then issue:
cp /usr/bin/spicer{,.orig}
echo '#!/bin/bash' > /usr/bin/spicer
echo 'timeout 10m spicer.orig "$#"' >> /usr/bin/spicer
Another approach would be to create a cronjob defintion into /etc/cron.d/kill_spicer. Like this:
* * * * * root kill $(ps --no-headers -C spicer -o pid,etimes | awk '$2>=600{print $1}')
The cronjob will get executed minutely and uses ps to obtain a list of spicer processes that run longer than 10minutes and passes them to kill.
Probably you even want kill -9 if the process is hanging.

You can use the -C option of ps to select processes by name.
ps --no-headers -C spicer -o pid,etime
Then you can use cut to filter the results, if the spacing is consistent. On my system the pid field takes up 8 characters, so I'd use
kill $(ps --no-headers -C spicer -o pid,etime | cut -c-8)
If the spacing is inconsistent (but if so, what kind of messed up ps are you using? :-P), you can use awk { print $1 } instead of cut.

Related

Run command as another user in Linux with `su - user c` creates a duplicate process

I want to run a process by a service as root user, because the daemon may have its own user.
But when I run it with system("su - root c ./testbin"), the system shows two processes (I check this via ps aux | grep testbin):
su - root c ./testbin
and
./testbin
How to achieve a single process?
The "su" process can not be avoided, but you can get it to end before your testbin does.
Your original question using "sleep" looks like this:
(su - root -c "sleep 120" &) ; ps aux | grep sleep
If you execute that line multiple times you will see multiple "su" processes as a result of the grep.
Backgrounding the subprocess allows the su process to end, like this:
(su - root -c "sleep 120 &" &) ; ps aux | grep sleep
When you execute that line multiple times you can see that the "su" processes disappear from the list but that the sleep commands continue.
Note that the ampersand inside the double quotes is for the sub process and that the ampersand just before the parentheses is for the 'su' command which is required to perform your question in a single line and speed up testing this case.
I checked if an equivalent of 'execv' exists for the command line, but this does not seem to be the case. Also, 'su' is a process that runs with the permissions of the caller and the subprocess of su runs with the permissions of the process forked by 'su'. It seems logical to me that you can not replace the 'su' process with its child as 'execv' does in 'C' for security reasons.
ps aux | grep testbin | grep -v grep
I think you just see your "grep" process. Use the command above.

Bash script commands not running

I have seafile (http://www.seafile.com/en/home/) running on my NAS and I set up a cron tab that runs a script every few minutes to check if the seafile server is up, and if not, it will start it
The script looks like this:
#!/bin/bash
# exit if process is running
if ps aux | grep "[s]eafile" > /dev/null
then exit
else
# restart process
/home/simon/seafile/seafile-server-latest/seafile.sh start
/home/simon/seafile/seafile-server-latest/seahub.sh start-fastcgi
fi
running /home/simon/seafile/seafile-server-latest/seafile.sh start and /home/simon/seafile/seafile-server-latest/seahub.sh start-fastcgi individually/manually works without a problem, but when I try to manually run this script file, neither of those lines execute and seafile/seahub do not start
Is there an error in my script that is preventing execution of those 2 lines? I've made sure to chmod the script file to 755
The problem is likely that when you pipe commands into one another, you don't guarentee that the second command doesn't start before the first (it can start, but not do anything while it waits for input). For example:
oj#ironhide:~$ ps -ef | grep foo
oj 8227 8207 0 13:54 pts/1 00:00:00 grep foo
There is no process containing the word "foo" running on my machine, but the grep that I'm piping ps to appears in the process list that ps produces.
You could try using pgrep instead, which is pretty much designed for this sort of thing:
if pgrep "[s]eafile"
Or you could add another pipe to filter out results that include grep:
ps aux | grep "[s]eafile" | grep -v grep
If the name of this script matches the regex [s]eafile it will trivially always take the exit branch.
You should probably be using pidof in preference of reinventing the yak shed anyway.
turns out the script itself was working ok, although the change to using pgrep is much nicer. the problem was actually in the crontab (didn't include the sh in the command)

How to get CPU usage from related processes?

If I run top -p $(pgrep -d',' scrapy) I get information on the scrapy process, but this process probably triggers other python related processes. How can I get information on these processes as well in real time as the top command does?
Thanks,
Dani
What you're looking for is a program or script that will gather the CPU usage of all child processes spawned by scrapy.
If you wanted to script this yourself, you could look at the output of ps -p {scrapy pid} -L to get all the threads spawned by the instantiation of scrapy.
Or, you could chain together a couple Linux commands to have a one-liner:
ps -C scrapy -o pcpu= | awk '{cpu_usage+=$1} END {print cpu_usage}'
ps:
-C specifies the command name to output
-o pcou= tells ps to only display cpu usage
awk:
{cpu_usage+=$1} END loops over the response from ps
{print cpu_usage} will send the sum to STDOUT.

Shell script to avoid killing the process that started the script

I am very new to shell scripting, can anyone help to solve a simple problem: I have written a simple shell script that does:
1. Stops few servers.
2. Kills all the process by user1
3. Starts few servers .
This script runs on the remote host. so I need to ssh to the machine copy my script and then run it. Also Command I have used for killing all the process is:
ps -efww | grep "user1"| grep -v "sshd"| awk '{print $2}' | xargs kill
Problem1: since user1 is used for ssh and running the script.It kills the process that is running the script and never goes to start the server.can anyone help me to modify the above command.
Problem2: how can I automate the process of sshing into the machine and running the script.
I have tried expect script but do I need to have a separate script for sshing and performing these tasksor can I do it in one script itself.
any help is welcomed.
Basically the answer is already in your script.
Just exclude your script from found processes like this
grep -v <your script name>
Regarding running the script automatically after you ssh, have a look here, it can be done by a special ssh configuration
Just create a simple script like:
#!/bin/bash
ssh user1#remotehost '
someservers stop
# kill processes here
someservers start
'
In order to avoid killing itself while stopping all user's processes try to add | grep -v bash after grep -v "sshd"
This is a problem with some nuance, and not straightforward to solve in shell.
The best approach
My suggestion, for easier system administration, would be to redesign. Run the killing logic as root, for example, so you may safely TERMinate any luser process without worrying about sawing off the branch you are sitting on. If your concern is runaway processes, run them under a timeout. Etc.
A good enough approach
Your ssh login shell session will have its own pseudo-tty, and all of its descendants will likely share that. So, figure out that tty name and skip anything with that tty:
TTY=$(tty | sed 's!^/dev/!!') # TTY := pts/3 e.g.
ps -eo tty=,user=,pid=,cmd= | grep luser | grep -v -e ^$TTY -e sshd | awk ...
Almost good enough approaches
The problem with "almost good enough" solutions like simply excluding the current script and sshd via ps -eo user=,pid=,cmd= | grep -v -e sshd -e fancy_script | awk ...) is that they rely heavily on the accident of invocation. ps auxf probably reveals that you have a login shell in between your script and your sshd (probably -bash) — you could put in special logic to skip that, too, but that's hardly robust if your script's invocation changes in the future.
What about question no. 2? (How can I automate sshing...?)
Good question. Off-topic. Try superuser.com.

How can I monitor the thread count of a process on linux?

I would like to monitor the number of threads used by a specific process on Linux.
Is there an easy way to get this information without impacting the performance of the process?
try
ps huH p <PID_OF_U_PROCESS> | wc -l
or htop
To get the number of threads for a given pid:
$ ps -o nlwp <pid>
Where nlwp stands for Number of Light Weight Processes (threads). Thus ps aliases nlwp to thcount, which means that
$ ps -o thcount <pid>
does also work.
If you want to monitor the thread count, simply use watch:
$ watch ps -o thcount <pid>
To get the sum of all threads running in the system:
$ ps -eo nlwp | tail -n +2 | awk '{ num_threads += $1 } END { print num_threads }'
Each thread in a process creates a directory under /proc/<pid>/task. Count the number of directories, and you have the number of threads.
cat /proc/<PROCESS_PID>/status | grep Threads
ps -eLf on the shell shall give you a list of all the threads and processes currently running on the system.
Or, you can run top command then hit 'H' to toggle thread listings.
$ ps H p pid-id
H - Lists all the individual threads in a process
or
$cat /proc/pid-id/status
pid-id is the Process ID
eg.. (Truncated the below output)
root#abc:~# cat /proc/8443/status
Name: abcdd
State: S (sleeping)
Tgid: 8443
VmSwap: 0 kB
Threads: 4
SigQ: 0/256556
SigPnd: 0000000000000000
If you use:
ps uH p <PID_OF_U_PROCESS> | wc -l
You have to subtract 1 to the result, as one of the lines "wc" is counting is the headers of the "ps" command.
My answer is more gui, but still within terminal. Htop may be used with a bit of setup.
Start htop.
Enter setup menu by pressing F2.
From leftmost column choose "Columns"
From rightmost column choose the column to be added to main monitoring output, "NLWP" is what you are looking for.
Press F10.
JStack is quite inexpensive - one option would be to pipe the output through grep to find active threads and then pipe through wc -l.
More graphically is JConsole, which displays the thread count for a given process.
Here is one command that displays the number of threads of a given process :
ps -L -o pid= -p <pid> | wc -l
Unlike the other ps based answers, there is here no need to substract 1 from its output as there is no ps header line thanks to the -o pid=option.
Newer JDK distributions ship with JConsole and VisualVM. Both are fantastic tools for getting the dirty details from a running Java process. If you have to do this programmatically, investigate JMX.
If you're looking for thread count for multiple processes, the other answers won't work well for you, since you won't see the process names or PIDs, which makes them rather useless. Use this instead:
ps -o pid,nlwp,args -p <pid_1> <pid_2> ... <pid_N>
In order to watch the changes live, just add watch:
watch ps -o pid,nlwp,args -p <pid_1> <pid_2> ... <pid_N>
jvmtop can show the current jvm thread count beside other metrics.
The easiest way is using "htop". You can install "htop" (a fancier version of top) which will show you all your cores, process and memory usage.
Press "Shift+H" to show all process or press again to hide it.
Press "F4" key to search your process name.
Installing on Ubuntu or Debian:
sudo apt-get install htop
Installing on Redhat or CentOS:
yum install htop
dnf install htop [On Fedora 22+ releases]
If you want to compile "htop" from source code, you will find it here.
If you are trying to find out the number of threads using cpu for a given pid I would use:
top -bc -H -n2 -p <pid> | awk '{if ($9 != "0.0" && $1 ~ /^[0-9]+$/) print $1 }' | sort -u | wc -l
If you want the number of threads per user in a linux system then you should use:
ps -eLf | grep <USER> | awk '{ num += $6 } END { print num }'
where as <USER> use the desired user name.
If you're interested in those threads which are really active -- as in doing something (not blocked, not timed_waiting, not reporting "thread running" but really waiting for a stream to give data) as opposed to sitting around idle but live -- then you might be interested in jstack-active.
This simple bash script runs jstack then filters out all the threads which by heuristics seem to be idling, showing you stack traces for those threads which are actually consuming CPU cycles.
First get the process ID (pid) by executing below command:
ps -ef | grep (for e.g ps -ef | grep java)
Now replace the pid in below command and execute to get the total thread count of a process.
ps huH p | wc -l
VisualVM can show clear states of threads of a given JVM process

Resources