- All about Linux init script
- What is an init script?
- Writing sample init script
- Explaining and enhancing sample init script
- Start a init script like a simple shell script
- Comment but no comment, chkconfig in comment, to set start and stop in init script
- Functions creation is helpful in init script
- case esac to accept the init script arguments
- Finalize and Execute the init script
- Adding sample init script to start at boot
- Deleting sample init script boot from system boot
- Use of service command with init script
- Пишем Init скрипт
- Пишем Upstart скрипт
- Примеры Init скрипта
All about Linux init script
What is an init script, what is the use of it, how to write an init script? Lets begin to know the answers.
Declaimer: Use it at your own risk. Writing this topic for learning and knowledge sharing purpose only. You must own root privileges (and authority) on the system where you are trying or applying this topic.
What is an init script?
Keeping it simple, init script is just a shell script which always starts with shebang. It is used to start an application on boot time and stop on shutdown. It can also be used to restart and to send various other instructions to the application.
So how to write this init script?
Writing sample init script
So its a shell script, a simple case esac shell script. Lets take following example:
#!/bin/sh # # Sample init script version 1 # Created by Rahul Panwar # # description: Describe the purpose of this shell script like every good documented shell script. # chkconfig: 2345 80 20 # start function will be executed on startup start() < echo start # start application command ># stop function will be executed on shutdown stop() < echo stop # stop application command >case "$1" in start) start ;; stop) stop ;; *) echo "invalid argument" exit 1 esac
This is an example init shell script, which is using start, stop as argument. Executing this script with start argument will call start function and stop will call stop function, other than those arguments will give error “invalid argument” and exit with error status 1.
Explaining and enhancing sample init script
Now you have a sample script which is starting at boot time. So its time to understand it part by part and enhance it for some real use.
Start a init script like a simple shell script
Like every shell script, it is also starting with shebang #!/bin/sh and some comments about the script.
#!/bin/sh # # Sample init script version 1 # Created by Rahul Panwar
Comment but no comment, chkconfig in comment, to set start and stop in init script
In comment line of init script, chkconfig means when to start the service and when to stop and in which runlevel.
# description: Describe the purpose of this shell script like every good documented shell script. # chkconfig: 2345 80 20
2345 after chkconfig: is showing the runlevels 2, 3, 4 and 5 where this init script will be started and other than that, like runlevels 0, 1 and 6, where it will be stopped.
After runlevel, 80 denotes the start sequence and 20 denotes the stop sequence.
So Don’t consider chkconfig as a comment in init script, set the start sequence and stop sequence as per the requirement.
NOTE: If same start and stop sequence is using in other scripts, init will sort them, to execute, by using there names.
Functions creation is helpful in init script
Functions in init script or in any shell script, makes it easy to read and understand. It helps to avoid code repetition.
For example, restart function can be added, which will use stop and start functions to restart the application.
# restart function will be executed for restarting the application restart()
Other important functions can also be added to script by using import method.
# start function will be executed on startup . /etc/init.d/functions
/etc/init.d/functions script contains several useful functions for init scripts like daemon (used to daemonize the application), killproc (To kill the running process id), status (to get the current status of running application or process id), etc.
So lets enhance our start and stop functions, by using some useful functions from /etc/init.d/functions script.
myname=`basename $0` helloapp=/usr/local/bin/sayhello RETVAL=0 # start function will be executed on startup start() < echo -n "Starting $myname: " # start application command daemon $helloapp RETVAL=$? [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$myname echo return $RETVAL ># stop function will be executed on shutdown stop() < echo -n "Stopping $myname: " # stop application command killproc $helloapp RETVAL=$? [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$myname echo return $RETVAL >
NOTE: Lock file creation in start and remove in stop is very important to write a perfect init script, to know more about it check my old post Use of Subsystem Lock Files in Init Scripts.
case esac to accept the init script arguments
Last but very essential part of init script is case esac. It also make init scripts easy to understand the allowed arguments and add more arguments.
case "$1" in start) start ;; stop) stop ;; restart) restart ;; status) status $helloapp ;; *) echo "Usage:So very easily two new cases, restart and status, are added to init script, which will allow start, stop, restart and status as init script arguments. Other than these arguments, it will goes to default section (*), where it will just show the usage to init script and exit.
Finalize and Execute the init script
Sample init script is explained and enhanced step by step, so lets collaborate all and prepare the final script.
#!/bin/sh # # Sample init script version 2 # Created by Rahul Panwar # # description: Run helloapp application as Linux service. # chkconfig: 2345 80 20 # start function will be executed on startup . /etc/init.d/functions myname=`basename $0` helloapp=/usr/local/bin/sayhello RETVAL=0 # start function will be executed on startup start() < echo -n "Starting $myname: " # start application command daemon $helloapp RETVAL=$? [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$myname echo return $RETVAL ># stop function will be executed on shutdown stop() < echo -n "Stopping $myname: " # stop application command killproc $helloapp RETVAL=$? [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$myname echo return $RETVAL ># restart function will be executed for restarting the application restart() < stop start >case "$1" in start) start ;; stop) stop ;; restart) restart ;; status) status $helloapp ;; *) echo "Usage: $myname" exit 1 ;; esac exit $? Adding sample init script to start at boot
This init script can be added to start at boot time, by using following steps:
- Save this init script to /etc/init.d/ directory with a name let say sample-init, where all Linux init scripts stores.
- Don’t forget to make it executable, by using Linux chmod command.
[root@rahul-pc ~]# chmod +x /etc/init.d/sample-init[root@rahul-pc ~]# chkconfig --add sample-init
- /etc/rc0.d/K20sample-init
- /etc/rc1.d/K20sample-init
- /etc/rc2.d/S80sample-init
- /etc/rc3.d/S80sample-init
- /etc/rc4.d/S80sample-init
- /etc/rc5.d/S80sample-init
- /etc/rc6.d/K20sample-init
These softlinks will be executed during boot at system runlevel. Softlink starts with S80 will execute with start argument (with 80 priority) and softlink starts with K20 will execute with stop argument (with 20 priority) on respective runlevel.
Verify the added init script.
[root@rahul-pc ~]# chkconfig --list sample-init sample-init 0:off 1:off 2:on 3:on 4:on 5:on 6:offAfter 4th step, it start showing 2:on, 3:on, 4:on, 5:on, means it is ready to start on boot at runlevel 2, 3, 4 and 5. All the priority and runlevel setting is the effect of chkconfig in comment section, described in above sectiosn.
You can now reboot your system and check its running.
Deleting sample init script boot from system boot
Following chkconfig command will be used to delete the sample-init script from system boot.
[root@rahul-pc ~]# chkconfig --del sample-initAll the softlinks created in add will be removed, that will stop it to execute on boot.
Use of service command with init script
service command can be used to pass the argument to init script, as follows:
[root@rahul-pc ~]# service sample-init start Starting sample-init: [ OK ][root@rahul-pc ~]# service sample-init status Subsysten sample-init is active with pid 1234[root@rahul-pc ~]# service sample-init restart Stopping sample-init: [ OK ] Starting sample-init: [ OK ][root@rahul-pc ~]# service sample-init stop Stopping sample-init: [ OK ]Using any other argument, it will show usage:
[root@rahul-pc ~]# service sample-init help Usage: sample-init
Пишем Init скрипт
Инициализация — важнейшая процедура, лежащая в основе любой операционной системы на основе Unix/Linux для управления работой каждого скрипта и службы.
Я описывал в своих статьях процесс создания скриптов для systemD/Upstart и сейчас я хотел бы написать о написании init скриптов. Тема не новая и используется давно, но я большую часть своих тем беру именно из черновиков, которые накопились за года 3-4. У меня не хватает времени на все публикации + наполнять контент максимально (по крайней мере, сразу) и по этому, имеет что имеем. Но не смотря на это, у меня уже довольно много читателей — и это хорошо, это радует!
По сути, инициализация следует за этим процессом:
- Загрузка сервера.
- Запуск init процесса (обычно как PID 1).
- Запуск предопределенного набора задач для запуска активируется последовательно.
Инициализация отвечает за то, чтобы сервер мог загрузиться и отключиться. В некоторых Unix/Linux дистрибутивах используется стандартный процесс инициализации init/systemD/Upstart.
Пишем Upstart скрипт
И так, хотелось бы рассказать как можно запускать томкат. Но для начала, нужно узнать какой механизм инициализации используется:
Т.к речь идет о sysv init/Upstart, то и продолжим тему.
PS: Вот еще полезное чтиво:
INIT скрипт может иметь следующие состояния:
- start — Служит командой для запуска службы.
- stop — Выполняет остановку службы.
- restart — Перезапуст службы, а по факту — остановка и затем запуск сервиса.
- reload — Перезагрузка службы, т.е команда для перечитывания конфигурации без перезапуска или остановки службы.
- force-reload — Перезагрузка конфигурации (перечитать конфиг), если служба поддерживает это. В противном случае — выполнит перезапуск службы.
- status — Покажет состояние службы.
Вот скилет скрипта для использования:
#!/bin/bash -x # # Source function library. . /etc/rc.d/init.d/functions case "$1" in start) echo -n "Starting services: " touch /var/lock/subsys/ ;; stop) echo -n "Shutting down services: " rm -f /var/lock/subsys/ ;; status) ;; restart) ;; reload) ;; probe) ;; *) echo "Usage:Данный каркас можно юзать для любых целей.
Примеры Init скрипта
Приведу наглядный пример запуска томката.
Запуск TOMCAT с init
Создадим init скрипт для запуска:
#!/bin/bash -x # # Provides: tomcat9 # Required-Start: $local_fs $remote_fs $network # Required-Stop: $local_fs $remote_fs $network # Should-Start: $named # Should-Stop: $named # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Start Tomcat. # Description: Start the Tomcat servlet engine. ### END INIT INFO export CATALINA_HOME=/usr/local/tomcat9 export JAVA_HOME=/usr/local/jdk1.8.0_131 export PATH=$JAVA_HOME/bin:$PATH service_name="tomcat9" start() < echo "Starting Tomcat 9. " /bin/su -s /bin/bash tomcat -c $CATALINA_HOME/bin/startup.sh >stop() < echo "Stopping Tomcat 9. " /bin/su -s /bin/bash tomcat -c $CATALINA_HOME/bin/shutdown.sh >status() < if (( $(ps -ef | grep -v grep | grep $service_name | wc -l) >0 )); then echo "$service_name is running. " else echo "$service_name is down. " fi > case $1 in start|stop|status) $1;; restart) stop; start;; *) echo "Usage : $0"; exit 1;; esac exit 0 Даем права на запуск (на исполнение):
# chmod 755 /etc/init.d/tomcat9Открываем браузер и смотрим что вышло!
#!/bin/bash -x DAEMON_PATH="/home/wes/Development/projects/myapp" DAEMON=myapp DAEMONOPTS="-my opts" NAME=myapp DESC="My daemon description" PIDFILE=/var/run/$NAME.pid SCRIPTNAME=/etc/init.d/$NAME case "$1" in start) printf "%-50s" "Starting $NAME. " cd $DAEMON_PATH PID=`$DAEMON $DAEMONOPTS > /dev/null 2>&1 & echo $!` #echo "Saving PID" $PID " to " $PIDFILE if [ -z $PID ]; then printf "%s\n" "Fail" else echo $PID > $PIDFILE printf "%s\n" "Ok" fi ;; status) printf "%-50s" "Checking $NAME. " if [ -f $PIDFILE ]; then PID=`cat $PIDFILE` if [ -z "`ps axf | grep $ | grep -v grep`" ]; then printf "%s\n" "Process dead but pidfile exists" else echo "Running" fi else printf "%s\n" "Service not running" fi ;; stop) printf "%-50s" "Stopping $NAME" PID=`cat $PIDFILE` cd $DAEMON_PATH if [ -f $PIDFILE ]; then kill -HUP $PID printf "%s\n" "Ok" rm -f $PIDFILE else printf "%s\n" "pidfile not found" fi ;; restart) $0 stop $0 start ;; *) echo "Usage: $0" exit 1 esac Подойдет к большинству скриптов, а для остальных — можно отредактировать немного.
И, вот еще полезный довольно вариант:
#!/bin/sh ### BEGIN INIT INFO # Provides: # Required-Start: $remote_fs $syslog # Required-Stop: $remote_fs $syslog # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Start daemon at boot time # Description: Enable service provided by daemon. ### END INIT INFO dir="" cmd="" user="" name=`basename $0` pid_file="/var/run/$name.pid" stdout_log="/var/log/$name.log" stderr_log="/var/log/$name.err" get_pid() < cat "$pid_file" >is_running() < [ -f "$pid_file" ] && ps -p `get_pid` >/dev/null 2>&1 > case "$1" in start) if is_running; then echo "Already started" else echo "Starting $name" cd "$dir" if [ -z "$user" ]; then sudo $cmd >> "$stdout_log" 2>> "$stderr_log" & else sudo -u "$user" $cmd >> "$stdout_log" 2>> "$stderr_log" & fi echo $! > "$pid_file" if ! is_running; then echo "Unable to start, see $stdout_log and $stderr_log" exit 1 fi fi ;; stop) if is_running; then echo -n "Stopping $name.." kill `get_pid` for i in 1 2 3 4 5 6 7 8 9 10 # for i in `seq 10` do if ! is_running; then break fi echo -n "." sleep 1 done echo if is_running; then echo "Not stopped; may still be shutting down or shutdown may have failed" exit 1 else echo "Stopped" if [ -f "$pid_file" ]; then rm "$pid_file" fi fi else echo "Not running" fi ;; restart) $0 stop if is_running; then echo "Unable to stop, will not attempt to start" exit 1 fi $0 start ;; status) if is_running; then echo "Running" else echo "Stopped" exit 1 fi ;; *) echo "Usage: $0" exit 1 ;; esac exit 0 Вот и все, статья «Пишем Init скрипт» завершена.