Init process interaction with shell cripts - linux

Nearly all linux courses say that init process, given the run level, will execute appropriate shell scripts to initialize the enivronment. But non of the courses describe in detail how init process does it.
As I understand the init process is basically a C program, much like any Hello World C code. Only much more sophisticated. Does anyone knows how this C program actually runs through all the scripts and invokes them?
I would really appreciate any answer and especially if you have a link to an example source code.

You can find explanations of what it does in different documentation:
http://www.centos.org/docs/5/html/5.1/Installation_Guide/s2-boot-init-shutdown-init.html
http://www.gentoo.org/doc/en/handbook/handbook-x86.xml?part=2&chap=4
and you can find its source code over there:
init.h
init.c
basically, init as process 1, has for role to fork() every application on your system. If you boot linux with the command line init=/bin/sh at boot time, process 1 forked by the kernel will be a shell. The sysvinit program makes it a bit more easy to handle a complex boot. It adds the concept of runlevels, define basic environment etc.. so that makes it easy to boot a system and have many services, and not only a shell. All that part is well explained in the documentations I gave you.
Does anyone knows how this C program actually runs through all the scripts and invokes them?
Well, is as simple as in your question. When you boot your system, init reads the inittab file, figures out what are your preferences (what is the default runlevel? what program to spawn? how many consoles?..), and for the chosen runlevel will fork a shell that will execute the startup script. Then that shell script will makes its way up to the shell script you activated from /etc/init.d. Usually the shell script part is very distribution-specific, that's why I gave you two links about that, and you may find it is different on ubuntu and debian...
For more details on the source code, you may want to start at the bottom of init.c which contains init's mainloop.
And +1 on your question for your curiosity!

Related

Respond Y dynamically to a shell program

We have a startup script for an application (Owned and developed by different team but deployments are managed by us), which will prompt Y/N to confirm starting post deployment. But the number of times it will prompt will vary, depends on changes in the release.
So the number of times it will prompt would vary from 1 to N (Might be even 100 or more than that).
We have automated the deployment and startup using Jenkins shell script jobs. But startup prompts number is hardcoded to 20 which might be more at sometime.
Could anyone please advise how number of prompts can be handled dynamically. We need to pass Y whenever there is pattern in the output "Do you really want to start".
Checked few options like expect, read. But not able to come up with a solution.
Thanks in advance!
In general, the best way to handle this is by (a) using a standard process management system, such as your distro's preferred init system; or, if that's not possible, (b) to adjust the script to run noninteractively (e.g., with a --yes or --noninteractive option).
Barring that, assuming your script reads from standard input and not the TTY, you can use the standard program yes and pipe it into the command you're running, like so:
$ yes | ./deploy
yes prints y (or its argument) over and over until it's killed, usually by SIGPIPE.
If your process is reading from /dev/tty instead of standard input, and you really can't convince the other team to come to their senses and add an appropriate option, you'll need to use expect for this.

How can I run a service when the runlevel changes

I want to automatically start the proftpd service when the runlevel changes from 2 to 5. When it changes back to 2 it should be stopped again.
Any ideas?
If you use sysvinit, the procedure is easy. Just have a K??yourServiceName script in /etc/rc2.d and a S??yourServiceName in /etc/rc5.d. They will be called with the runlevel in $RUNLEVEL environment variable and with a stop and start (respectively) parameters. The ?? represent two digits that represent the order of execution to use (priority?).
This has been replaced in new scripts (mainly in debian, but I think others follow this approach also) by having several fields in the scripts themselves indicating the dependencies between scripts and execution is done in parallel for scriptis that don't depend on each other, but serially for scripts that depend between themselves. You can read about this approach in the scripts themselves. The scripts are installed normally in /etc/init.d, and symbolic links are made from there to the proper directory with the proper two digit positions by the utilities controlling this.
Finally, if you use systemd (it has replaced completely the sysv init process) there's another method to deal with it. You'll have to look for the doc of systemd(8) ad I'm not aware of it. I only know it's a dbus service provider and processes comunicate with it via this new technology.
The two first methods are somewhat interoperable, as if you fix the priority of execution and don't fill the dependencies, the system v init process will respect it.
Edit
This approach assumes you run proftpd as an independent service (not as dependant of xinetd(8) or inetd(8)) and it has scripts to launch and stop it on a runlevel change.
In case you need to run it depending on xinetd(8), i don't know now if xinetd has parameters to allow you to serve based on the runlevel. If it has, you are lucky. If it hasn't you will have to switch your approach.

How can I identify a progam by pid

My title is more than no explicite so feel free to change it (don't really know how to name it)
I use a php script to check if a list of pid is running, My issue is that pid identifying is not enough and some other program can get the pid number later on when mine is over.
So, is there something I can do to identify than pid is the good pid that I need to check and not another one.
I think to hash /proc/<pid>/cmdline but even that is not 100% safe (another program can be the same software and the same parameters (it's rare but possible).
if an example is needed:
I run several instance of wget
one of them have PID number 8426
some times later…
I check if PID 8426 is running, it is so my php script react and don't check file downloaded but the fact is that PID 8426 of wget is over and it's another program that running pid 8426.
If the new program run for a long time (eg: a service) I can wait a long time for my php script to check the downloaded file.
Have you tried employing an object-oriented paradigm, where you could encapsulate the specific PID number into its specific object (i.e., specific program)? To accomplish this, you need to create a class (say you give it the arbitrary name "SOURCE") from which these programs can be obtained as objects belonging to that class. Doing so will encapsulate any information (e.g., PID), including the methods of that specific program to that program alone and, therefore, provide a safer way than doing a hash. Similar methods can be found in the object-oriented programming paradigm of Python.
You can read the binary file that /proc/<pid>/exe points to. The following concept is done in a shell but probably can do that in any language including php:
$ readlink "/proc/$$/exe"
/bin/bash

Linux: Default prioirty of applications that run dynamically as tasks

I'm a new user of linux and am confused about task priorities of applications that run dynamically at run time.
Here's the scenario:
1. I create an application called myApplication and install it in one of the bin folders (/usr/sbin)
2. This task is not run until
a. I start it specifically from shell or
b. I call it from a script based on some event.
The application executes and terminates.
How do I know its priority?
Q2. Will it take default priority and nice value? I see that my application's nice value is 0 which I assume is default.
Q3. How can I find the priority of all such applications that are installed in one of the bin folders but are called run time and terminate after their desired work is done?
I thoroughly searched the forum before posting this query and I apologize if it has already been answered.
Many many thanks in advance.
Keshav
Programs don't generally have an associated nice value. The default is for spawned processes to inherit the parent's niceness, regardless of which program is being started. To change this you can use the nice or renice command-line utilities, or the setpriority() system call.

Difference between execv and just running an app?

We have an stub that we are launching from inittab that execv's our process. (ARM Linux Kernel 2.6.25)
When testing the process it fails only if launched from inittab and execv'd. If launched on the command line it work perfectly, every time.
The process makes heavy use of SYS V IPC.
Are there any differences between the two launch methods that I should be aware of?
As Matthew mentioned it, it is probably an env variable issue. Try to dump yout env list before calling your program in both case - through the stub or 'by hand'.
BTW It could help a lot if you could provide more information why your program did crash. Log file ? core dump/gdb ? return value from execve ?
Edit:
Other checks: are you sure to pass exactly the same parameter list (if there are parameters)?
To answer your question , there is no differences between the 2 methods. Actually your shell fork() and finally call execve() to launch your process, feeding it with parameters you've provided by hand, and the environement variables you've set in your shell. Btw when launching your program through init it could launch it during an early stage of your machine startup. Are you sure everything is ready for the good running of your application at that point?
Could it be an issue of environment variables? If so, consider using execve or execle with an appropriate envp argument.
The environment variable suggestion is pretty good - specifically I'd check $PATH to make sure your dependent libraries are being found (if you have any). Another thing you could check is, are you running under the same uid/gid when run as inittab?
And if you replace your stub with a shell script ?
If it works from the command line, it should work from a shell script, and you can know wether it is your stub or the fact that it is in inittab.
Could it be a controlling tty issue ?
Another advantage of the shell script is you can edit it and strace your program to see where it fails
Was a mismatched kernel/library issue. Everything cleaned up after a full recompile.

Resources