How to add a different scheduler to a shell script in Linux? - linux

I am trying to use different schedulers to measure CPU usage among various programs. I am currently having trouble figuring out how to add a different scheduler to the script. I have tried using the chrt command, but I can not reliably get the pid for the script.

PIDs are fickle and racy (only the parent process of a PID can be sure it hasn't died and been recycled).
I'd use the first form (chrt [options] prio command [arg]...
) instead, relying on two scripts:
wrapper_script:
exec chrt --fifo 99 wrapee #wrapee must be in $PATH
wrapee:
echo "I'm a hi-priority hello world"

Related

How do I stop a scirpt running in the background in linux?

Let's say I have a silly script:
while true;do
touch ~/test_file
sleep 3
done
And I start the script into the background and leave the terminal:
chmod u+x silly_script.sh
./silly_script.sh &
exit
Is there a way for me to identify and stop that script now? The way I see it is, that every command is started in it's own process and I might be able to catch and kill one command like the 'sleep 3' but not the execution of the entire script, am I mistaken? I expected a process to appear with the scripts name, but it does not. If I start the script with 'source silly_script.sh' I can't find a process by the name of 'source'. Do I need to identify the instance of bash, that is executing the script? How would I do that?
EDIT: There have been a few creative solutions, but so far they require the PID of the script execution to be stored right away, or the bash session to not be left with ^D or exit. I understand, that this way of running scripts should maybe be avoided, but I find it hard to believe, that any low privilege user could, even by accident, start an annoying script into the background, that is for instance filling the drive with garbage files or repeatedly starting new instances of some software and even the admin has no other option, than to restart the server, because a simple script can hide it's identifier without even trying.
With the help of the fine people here I was able to derive the answer I needed:
It is true, that the script runs every command in it's own process, so for instance killing the sleep 3 command won't do anything to the script being run, but through a command like the sleep 3 you can find the bash instance running the script, by looking for the parent process:
So after doing the above, you can run ps axf to show all processes in a tree form. You will then find this section:
18660 ? S 0:00 /bin/bash
18696 ? S 0:00 \_ sleep 3
Now you have found the bash instance, that is running the script and can stop it: kill 18660
(Of course your PID will be different from mine)
The jobs command will show you all running background jobs.
You can kill background jobs by id using kill, e.g.:
$ sleep 9999 &
[1] 58730
$ jobs
[1]+ Running sleep 9999 &
$ kill %1
[1]+ Terminated sleep 9999
$ jobs
$
58730 is the PID of the backgrounded task, and 1 is the task id of it. In this case kill 58730 and kill %1` would have the same effect.
See the JOB CONTROL section of man bash for more info.
When you exit, the backgrounded job will get a kill signal and die (assuming that's how it handles the signal - in your simple example it is), unless you disown it first.
That kill will propogate to the sleep process, which may well ignore it and continue sleeping. If this is the case you'll still see it in ps -e output, but with a parent pid of 1 indicating its original parent no longer exists.
You can use ps -o ppid= <pid> to find the parent of a process, or pstree -ap to visualise the job hierarchy and find the parent visually.

Howto debug running bash script

I have a bash script running on Ubuntu.
Is it possible to see the line/command executed now without script restart.
The issue is that script sometimes never exits. This is really hard to reproduce (now I caught it), so I can't just stop the script and start the debugging.
Any help would be really appreciated
P.S. Script logic is hard to understand, so I can't to figure out why it's frozen by power of thoughts.
Try to find the process id (pid) of the shell, you may use ps -ef | grep <script_name>
Let's set this pid in the shell variable $PID.
Find all the child processes of this $PID by:
ps --ppid $PID
You might find one or more (if for example it's stuck in a pipelined series of commands). Repeat this command couple of times. If it doesn't change this means the script is stuck in certain command. In this case, you may attach trace command to the running child process:
sudo strace -p $PID
This will show you what is being executed, either indefinite loop (like reading from a pipe) or waiting on some event that never happens.
In case you find ps --ppid $PID changes, this indicates that your script is advancing but it's stuck somewhere, e.g. local loop in the script. From the changing commands, it can give you a hint where in the script it's looping.

Kill a "background process" in Linux using a C Program

I have started my process in background and I would like to kill that process using a C program using popen().
I have tried in many ways but in vain. The reason is when I run a C code, it is executed in a sub-shell because of which I can't get the processes running in main shell.
I used $! to get the latest pid running in the background, but because of the above reason it didn't work.
my_process & pids="${pids-} $!" //start my process
sleep 10 // run for 10 seconds
kill -2 $pids //kill the process
Also you can store PID in file and kill it.like
./process1.sh &
echo $! > /tmp/process1.pid
kill -9 `cat /tmp/process*.pid`
rm /tmp/process*.pid
You should make your process into a daemon, that way you can start, end and restart it without complications.
You can start here: Best way to make a shell script daemon?
+1 on Raydel's answer
Another alternative (since there are so many ways to do things) If you have root you can also create it as a service and then start it and stop it manually using the "service" commands.
(Sorry wanted to add as a comment to Raydel's but my rep is not high enough apparently so adding as a separate answer)

Get PID of a process as it opens

How do I get the pid of a process as soon as it opens. Like lets say we run ./file.pl and then ./file2.pl As both these files will create a pid in /proc/ folder. How do I instantly know if the process has been created when the executable is run.
I have a file with all the commands ready to be run as soon as it gets the green signal that there is a new process in the /proc/ folder. How do I do that?
EDIT:
Please don't answer with a shell command. I don't need to know the pid. I need to develop a script which can know right away that we have a guest in the proc department
If you start the process via a shell, then start process in background:
./your_prog &
Get the pid:
echo $!
If the script give you the shell prompt back, you can do :
./your_prog
pidof -x your_prog
Tested OK with this perl script :
#!/usr/bin/perl
if (fork() == 0) {
sleep(600);
}
you need to
chmod +x your_prog
before...
Every process can get its own pid with the getpid(2) syscall. At process creation by fork(2) the parent process (e.g. some shell) gets the pid of the new child process. Read e.g. Advanced Linux Programming for more. And the kernel (not the program) is creating some subdirectory /proc/1234/ see proc(5) as soon as it creates the process of pid 1234.
Actually, /proc/ is not a real file system. It is just a pseudo file system giving a view on the state of the kernel and the entire Linux system.
Perl gives you its POSIX module to interface the syscalls. The getpid() syscall is interfaced using the $PID or $$ Perl variable.
The /proc/ pseudo filesystem is filled by the kernel. You could perhaps use inotify to follow change in /proc/ but this is very probably a bad idea.
Your question is not clear, we cannot understand what you really want to do and what you have tried.
Try out below shell script.(You may have to include changes in below script for your expected output)
#!/bin/bash
nr_proc_before=`ls -l /proc | wc -l`
ls /proc > proc_list_before
./any_executable &
nr_proc_after=`ls -l /proc | wc -l`
ls /proc > proc_list_after
nr_new=`expr $nr_proc_after - $nr_proc_before`
echo "$nr_new processes are created newly"
echo "new processes pids are :"
diff proc_list_after proc_list_before > new_pids
sed "1d" new_pids
if [ nr_new > 0 ] ; then
#trigger your file which has commands.
fi
Insted of any_execuatble you can replace with your things so that new processes will be created.
Note : This is not a script which monitors for new process. This sample of script may give you idea to solve your problem.
Please do reply for this answer, i can redefine my answer.

linux: suspend process at startup

I would like to spawn a process suspended, possibly in the context of another user (e.g. via sudo -u ...), set up some iptables rules for the spawned process, continue running the process, and remove the iptable rules when the process exists.
Is there any standart means (bash, corutils, etc.) that allows me to achieve the above? In particular, how can I spawn a process in a suspended state and get its pid?
Write a wrapper script start-stopped.sh like this:
#!/bin/sh
kill -STOP $$ # suspend myself
# ... until I receive SIGCONT
exec $# # exec argument list
And then call it like:
sudo -u $SOME_USER start-stopped.sh mycommand & # start mycommand in stopped state
MYCOMMAND_PID=$!
setup_iptables $MYCOMMAND_PID # use its PID to setup iptables
sudo -u $SOME_USER kill -CONT $MYCOMMAND_PID # make mycommand continue
wait $MYCOMMAND_PID # wait for its termination
MYCOMMAND_EXIT_STATUS=$?
teardown_iptables # remove iptables rules
report $MYCOMMAND_EXIT_STATUS # report errors, if necessary
All this is overkill, however. You don't need to spawn your process in a suspended state to get the job done. Just make a wrapper script setup_iptables_and_start:
#!/bin/sh
setup_iptables $$ # use my own PID to setup iptables
exec sudo -u $SOME_USER $# # exec'ed command will have same PID
And then call it like
setup_iptables_and_start mycommand || report errors
teardown_iptables
You can write a C wrapper for your program that will do something like this :
fork and print child pid.
In the child, wait for user to press Enter. This puts the child in sleep and you can add the rules with the pid.
Once rules are added, user presses enter. The child runs your original program, either using exec or system.
Will this work?
Edit:
Actually you can do above procedure with a shell script. Try following bash script:
#!/bin/bash
echo "Pid is $$"
echo -n "Press Enter.."
read
exec $#
You can run this as /bin/bash ./run.sh <your command>
One way to do it is to enlist gdb to pause the program at the start of its main function (using the command "break main"). This will guarantee that the process is suspended fast enough (although some initialisation routines can run before main, they probably won't do anything relevant). However, for this you will need debugging information for the program you want to start suspended.
I suggest you try this manually first, see how it works, and then work out how to script what you've done.
Alternatively, it may be possible to constrain the process (if indeed that is what you're trying to do!) without using iptables, using SELinux or a ptrace-based tool like sydbox instead.
I suppose you could write a util yourself that forks, and wherein the child of the fork suspends itself just before doing an exec. Otherwise, consider using an LD_PRELOAD lib to do your 'custom' business.
If you care about making that secure, you should probably look at bigger guns (with chroot, perhaps paravirtualization, user mode linux etc. etc);
Last tip: if you don't mind doing some more coding, the ptrace interface should allow you to do what you describe (since it is used to implement debuggers with)
You probably need the PID of a program you're starting, before that program actually starts running. You could do it like this.
Start a plain script
Force the script to wait
You can probably use suspend which is a bash builitin but in the worst case you can make it stop itself with a signal
Use the PID of the bash process in every way you want
Restart the stopped bash process (SIGCONT) and do an exec - another builtin - starting your real process (it will inherit the PID)

Resources