Run a cleanup script when stopping a Docker container - bash

My Dockerfile looks like this:
FROM ubuntu:latest
# ... there is more
ENTRYPOINT ["/root/startup.sh"]
CMD ["choose_random"]
So startup.sh is called with a default paramater if none is provided by the user.
My startup.sh is this one:
#!/bin/bash
# init database etc.
python3 /root/boot.py $1
# snmpd
/usr/sbin/snmpd -f -Lo &
# logger
tail -f /var/log/mylog.log
Now I want to simply call cleanup.py whenever a SIGTERM is received. I saw a few examples but my knowledge about the bash syntax is too little to actually understand and transfer onto my situation. I understand that I need a SIGTERM trap, but how do I actually call the cleanup script a wait until it's finished?
Thanks in advance!
Markus

Have you tried this method?
If it works, you can just change what's inside the function to call your cleanup script.

Related

Python2.7 use subprocess.Popen to kubectl exec into the bash of a pod not working

previously I was using a python statement like
os.system("kubectl exec --it bash xxx") to exec into a kubernetes pod, it ends up redirect me to the bash of the pod and I could type commands directly. Someone recommended using subprocess.Popen instead because it is safer, so I tried something like
subprocess.Popen(["kubectl", "exec"] + kube_args + ["-it", pod_name, "--", "bash"],
stdout=subprocess.PIPE)
the python script run through, but it end up like nothing has happened(not redirecting me to the interactive bash of the pod. What should be the correct equivalent of the command in order to achieve this? Thank you.
That's the primitive, and you're calling it correctly.
You get back a subprocess proc, which you can
further interact with:
proc = Popen( ... )
or better:
with Popen( ... ) as proc:
There are some convenience functions
layered on top of the primitive.
check_call() makes the most sense, here.
It will patiently wait for the child to die,
typically when you type "exit" at the remote bash.
It calls Popen() for you and manages the details,
so you don't have to.

Run Script on AWS #reboot?

I'm currently trying to run script that will run in the background when my AWS instance boots for the duration of the instance life. I'm testing it with a simple script to see if it works, before I test with my more complicated one:
#!/bin/bash
while [true]; do
sleep 1
echo "Hello World" >> "tempStorage.json"
done
And my sudo crontab -l returns:
# All the comment stuff
#reboot sh /home/ubuntu/test/testScript/test.sh
Which is the path to the script. I've also obviously run chmod +x test.sh to make sure its an executable.
The problem is when I stop and then start the AWS instance there's nothing in the tempStorage.json file. I've checked other threads and they all suggest this is what I should be doing, so I'm very confused and advice would be appreciated. Thanks.
As Mark B mentioned, the issue is the execution directory of the cron script. There are two solutions then.
A) Change the path to file as Mark B recommended so the script would look something like:
#!/bin/bash
while [true]; do
sleep 1
echo "Hello World" >> "/home/ubuntu/test/testScript/tempStorage.json"
done
B) Change the directory of the cron execution and keep the script as it was. This works better if you need to put the script in any directory. It would look like this for the crontab:
# All the comment stuff
#reboot cd /home/ubuntu/test/testScript && sh test.sh
That should work fine. I think the issue is that you aren't giving the full path to the tempSTorage.json file within your script. So it is being written to in a different folder than the one you are looking in, specifically whatever folder cron starts processes in by default. Try changing it to something like /tmp/tempSTorage.json and then rebooting the server again.
Note that if you are wanting something that starts on boot and runs forever, this probably isn't the best method. In that case I would look into running your process as a service.

Shell script to call daemon - DAEMON: command not found

Currently I can start a custom server like this:
cd /home/admin/service/build && ./service visual.dat
I'm trying to make a shell script to make a daemon. I tried many things...
#!/bin/sh -e
cd /home/admin/service/build
DAEMON = "./service"
daemon_OPT="service.dat"
...
The response is:
admin#service:~$ sudo /etc/init.d/servicedaemon start
/etc/init.d/servicedaemon: line 3: DAEMON: command not found
Well, how to launch the service from the daemon like I did from the shell ? It's probably a path issue.
Thanks in advance.
I think you have to remove the spaces around "=":
DAEMON="./service"
Now it seems that it tries to run a command called DAEMON instead of the actual application.

Puppet init script doesn't create the pid file?

CentOS release 5.4 (Final)
puppet-server-2.7.19-1.el5 is installed from the puppetlabs repo.
puppetmaster is started successfull, but it doesn't create the pid file. It is the reason for [ FAILED ] message when stopping:
/etc/init.d/puppetmaster stop
Stopping puppetmaster: [FAILED]
The init script: http://fpaste.org/nsfI/
The /etc/rc.d/init.d/functions library: http://fpaste.org/ox5Q/
And this is what I get when running in the debug mode: http://fpaste.org/DkoS/
I know the way to echo the pid to a file manually after starting, but why doesn't daemon function's --pidfile work?
daemon $PUPPETMASTER $PUPPETMASTER_OPTS --masterport=${PUPPETMASTER_PORTS[$i]} --pidfile=/var/run/puppet/puppetmaster.${PUPPETMASTER_PORTS[$i]}.pid
Sure, Puppet master is running as puppet user:
ps -ef | grep [p]uppet
puppet 23418 1 0 18:13 ? 00:00:00 /usr/bin/ruby /usr/sbin/puppetmasterd
and the owner of /var/run/puppet/ folder is puppet:
# ls -ld /var/run/puppet/
drwxr-xr-x 2 puppet puppet 4096 Sep 17 18:46 /var/run/puppet/
It is up to the controlled program (in this case puppetmasterd), not the daemon() function, to create the pidfile; daemon() relies on this.
Confirm where puppetmasterd creates its pidfile (it could be /var/run/puppet.pid, /var/lib/puppet/run/master.pid, etc.) To find out, inspect the contents of puppetmasterd (if a script), or kill puppetmasterd then strace -f puppetmasterd 2>&1 | grep '\.pid'.
Modify the value of pidfile in your /etc/init.d/puppetmaster accordingly.
So, it looks to me like there could be a couple of possibilities here:
If you are trying to use the --pidfile option of the daemon command I believe you have a syntax problem.
Red Hat's daemon command has the following (unhelpful) signature: Usage: daemon [+/-nicelevel] {program}. What isn't altogether clear is that anything that you include after the program location is treated as an option passed to the program, not to the daemon function call.
So, in your case you are passing the --pidfile argument to $PUPPETMASTER itself as opposed to daemon(). You could remedy this by using the following: daemon --pidfile=/var/run/puppet/puppetmaster.${PUPPETMASTER_PORTS[$i]}.pid $PUPPETMASTER $PUPPETMASTER_OPTS --masterport=${PUPPETMASTER_PORTS[$i]}
The second option here is that $PUPPETMASTER (or rather, the program behind it) might daemonize itself, and if so, could be responsible for creating its own .pid file. The process management tool Circus works in this way. It's probably an option in a configuration file or for the program representing by $PUPPETMASTER.
I'm not a Puppet user, so I won't be able to help you with the specifics here. But I would look into the Puppet labs documentation to find out more about this option.
It is important to note if $PUPPETMASTER is daemonizing itself, then the --pidfile argument being passed to daemon() will have no effect.
Good hunting!

Running a delayed command with 'sudo'

I want run a Bash script as root, but delayed. How can I achieve this?
sudo "sleep 3600; command" , or
sudo (sleep 3600; command)
does not work.
You can use at:
sudo at next hour
And then you have to enter the command and close the file with Ctrl+D. Alternatively you can specify commands to be run in a file:
sudo at -f commands next hour
If you really must avoid using cron:
sudo sh -c "(sleep 3600; command)&"
The simplest answer is:
sudo bash -c 'sleep 3600; command' &
Because sleep is a shell command and not an executable, and the semicolon is a shell “operator” too, it is a shell script, and hence needs to run in a shell. bash -c tells sudo to run bash and pass it a script to execute as a string.
Of course this will “hang” until command has actually finished running, or be killed if you exit the surrounding shell. I haven’t found a simple way to use nohup to prevent that here, and at that point, you’re basically reimplementing the at command anyway. I have found the above solution useful in many simple cases though. ;)
For anything more complex… of course you can always make a real shell script file, with a shebang (#! …) at the start, and run that. But I assume the whole point is that you wanted to avoid this for something that simple.
You could theoretically pass a string as a file using Bash’s … <( … ) syntax, but sudo expects it to be a real file, and marked as executable too, so that won’t work.
Use:
sleep 3600; sudo <command>
Anyway, I would consider using cron in your case…

Resources