Daemonizing an executable in ansible - shell

I am trying to create a task in ansible which executes a shell command to run an executable in daemon mode using &. Something like following
-name: Start daemon
shell: myexeprogram arg1 arg2 &
What am seeing is if I keep & the task returns immediately and the process is not started . If I remove & ansible task waits for quite some time without returning.
Appreciate suggestion on proper way to start program in daemon mode through ansible. Pls note that I dont want to run this as a service but an adhoc background process based on certain conditions.

Running program with '&' does not make program a daemon, it just runs in background. To make a "true daemon" your program should do steps described here.
If your program is written in C, you can call daemon() function, which will do it for you. Then you can start your program even without '&' at the end and it will be running as a daemon.
The other option is to call your program using daemon, which should do the job as well.
- name: Start daemon
shell: daemon -- myexeprogram arg1 arg2

When you (or Ansible) log out the exit signal will still be sent to the running process, even though it is running in the background.
You can use nohup to circumvent that.
- name: Start daemon
shell: nohup myexeprogram arg1 arg2 &
http://en.wikipedia.org/wiki/Nohup

From the brief description on what you want to achieve, it sounds like it would be best for you to set up your executable as a service (using Upstart or similar) and then start/stop it as needed based on the other conditions that require it to be running (or not running).
Trying to run this as a process otherwise will entail having to capture the PID or similar so you can try and shut down the daemon you have started when you need to, with pretty much the same amount of complexity as installing an init config file would take and without the niceties that systems such as Upstart give you with the controls such as start/stop.

I found the best way, particularly because I wanted output to be logged, was to use the "daemonize" package. If you are on CentOS/Redhat, like below. There is probably also an apt-package for it.
- name: yum install daemonize
yum:
name: daemonize
state: latest
- name: run in background, log errors and standout to file
shell: daemonize -e /var/log/myprocess.log -o /var/log/myprocess.log /opt/myscripts/myprocess.sh

Adding to the daemonize suggestions above, if you want to start your program in a specific directory you can do:
- name: install daemonize package
package:
name: daemonize
state: latest
- name: start program
command: daemonize -c /folder/to/run/in /path/to/myexeprogram arg1 arg2
Notably, you also probably want the -e -o flags to log output.

Related

Vagrant shell incompatible with foreground "server boot" commands

I'm running a shell script on vagrant up via the inline shell config of a Vagrantfile. One of the commands starts up a tomcat web server which normally runs in the foreground.
My dilemma is that a) the commands in the vagrant shell script should exit or run in the background so that the prompt returns to the user correct, and b) if I send the output to the background with & the output isn't visible and the user has no idea when the web server has finished booting.
I either need a way to send output to the background and tell the user when the server has booted, or a way to send to the background once the server has booted. Without messing with the maven/tomcat side I don't see a way to do it.
$script = <<-SCRIPT
# other commands here
mvn tomcat7:run &
SCRIPT
config.vm.provision "shell", inline: $script, privileged: false, run: "always"
I use nohup command for this and redirect the output of the command in the specific log file - It does not fully answer the and tell the user when the server has booted
here's an example of a command I run
nohup java -jar /test/selenium-server-standalone-$1.jar -role hub &> /home/vagrant/nohup.grid.out&
If from the provisioning shell you'd want to give as much as possible information to the user, you could use sleep like 5/10 seconds (depending your deployment) then run tail -20 <log_file> so that would give users a good status of the progress of the task

How to run shell script on VM indefinitely?

I have a VM that I want running indefinitely. The server is always running but I want the script to keep running after I log out. How would I go about doing so? Creating a cron job?
In general the following steps are sufficient to convince most Unix shells that the process you're launching should not depend on the continued existence of the shell:
run the command under nohup
run the command in the background
redirect all file descriptors that normally point to the terminal to other locations
So, if you want to run command-name, you should do it like so:
nohup command-name >/dev/null 2>/dev/null </dev/null &
This tells the process that will execute command-name to send all stdout and stderr to nowhere (instead of to your terminal) and also to read stdin from nowhere (instead of from your terminal). Of course if you actually have locations to write to/read from, you can certainly use those instead -- anything except the terminal is fine:
nohup command-name >outputFile 2>errorFile <inputFile &
See also the answer in Petur's comment, which discusses this issue a fair bit.

Chef - Run long running script in background

I want to run a simple script in the background. It needs to be alive for the duration of the entire life of the machine.
script "my_script" do
interpreter "ruby"
cwd "/home/my_home"
user "root"
code << -EOH
pid = fork
if pid
Process.detach(pid)
system("ruby the_actual_script.rb > logfile")
end
EOH
But this does not seem to run, it appears it has run and exited immediately. There is a 0 size logfile. I have the cwd folder set to 777 permission.
Can't figure out what the issue is. I am guessing chef executes this in a different shell and gets rid of all processes once it exits that shell?
Is there a better way to simply run the script in the background?
What you describe is called a "service". You can place your script in his own file, for example using the "cookbook_file" chef resource. Then write an init script for it, for example using upstart in Ubuntu systems. Once you have an init script, you can use chef's "service" resource to make sure the service is enabled to always run, and that it is started during the first chef run that creates it. Voila!

How to run a process in the background inside Gvim?

Well, what I need to do actually is CTRL-Z out of a process that got started from insert mode in GVim.
My command :Cdprun executes cdprun.sh which runs a sudo-ed daemon. I can add & at the end of the sudo-ed daemon call to run in the background and that works but the user doesn't get prompted for a password. Instead I want to just CTRL-Z out of it but the keyboard interrupt doesn't work. Any ideas? Thx.
You generally have two options in this case: generic is using something like vim-addon-async mentioned by #Nicalas Martin or vim with built-in interpreters support: tcl with expect module, python with pyexpect, perl with Expect, maybe something else (note: all of the mentioned packages are not shipped with tcl/python/perl). Second is specific to current situation: it is backgrounding in the other place. From your explanation I guessed that you have a script looking like
#!/bin/sh
<...>
sudo run-daemon --daemon-args # Last executed line
, am I right? Than you can just put backgrounding in another place: not
sudo run-daemon --daemon-args &
, but
sudo sh -c "nohup run-daemon --daemon-args &"
Here is a script to deal with asynchronous command in vim. Not a perfect solution but could be a good temporary solution. http://www.vim.org/scripts/script.php?script_id=3307

How do I write a bash script to restart a service if it dies?

I have a program that runs as a daemon, using the C command fork(). It creates a new instance that runs in the background. The main instance exists after that.
What would be the best option to check if the service is running? I'm considering:
Create a file with the process id of the program and check if it's running with a script.
Use ps | grep to find the program in the running proccess list.
Thanks.
I think it will be better to manage your process with supervisord, or other process control system.
Create a cron job that runs every few minutes (or whatever you're comfortable with) and does something like this:
/path/to/is_script_stopped.sh && /path/to/script.sh
Write is_script_stopped.sh using any of the methods that you suggest. If your script is stopped cron will evaluate your script, if not, it won't.
To the question, you gave in the headline:
This simple endless loop will restart yourProgram as soon as it fails:
#!/bin/bash
for ((;;))
do
yourProgram
done
If your program depends on a resource, which might fail, it would be wise to insert a short pause, to avoid, that it will catch all system resources when failing million times per second:
#!/bin/bash
for ((;;))
do
yourProgram
sleep 1
done
To the question from the body of your post:
What would be the best option to check if the service is running?
If your ps has a -C option (like the Linux ps) you would prefer that over a ps ax | grep combination.
ps -C yourProgram

Resources