How to run cron job manually and check the logs in ubuntu - docker

I need to check the printed logs inside my cron file in ubuntu/cent os server. I am explaining my code below.
backup-mongodb.sh
#!/bin/bash
name = "uBot_sandbox"
export DATABASE_NAME="planets"
export BACKUP_LOCATION="/home/UBOT"
for container_name in $(docker ps --filter="name=$name" -q);do
echo "container name : $container_name"
done
I set this file using crontab -e like below.
* * * * * /bin/bash /home/subhrajp/UBOT/git/uBot/python3.7-alpine3.8/app/mean-stack/node-js/utils/backup-mongodb.sh
Here I need to check the echo output of that .sh file once the cronjob started. Also I need to know what is the command to run the cron file manually without starting the cronjob so that I can use it while developing. Please help me to resolve my problem.

Related

Docker container environment variable file during runtime

I have a docker image that basically schedules a cron job at a frequency defined when building the image using the below.
COPY myjobtime /etc/cron.d/myjobtime
RUN chmod 0644 /etc/cron.d/myjobtime &&\
crontab /etc/cron.d/myjobtime
CMD cron
I have the cron entry in the file myjobtime.
*/10 * * * * /usr/local/bin/sh /app/myscript.py
I would like to be able to pass the cron schedule during the runtime. Meaning, if someone wants to modify the cron schedule to a different frequency, they should be able to do that while running the container and passing an environment variable file with the new cron schedule in it. Can this be done?
The important detail is that you need to create and install the crontab file when the container starts up. I find an entrypoint wrapper script to be a useful pattern for this: set the image's ENTRYPOINT to be a shell script that does whatever first-time setup is required, then have it exec "$#" to run the image's CMD.
If your image is ultimately based on a Linux distribution based on the GNU toolset, then envsubst is a really helpful program here. It reads in a text file, expands environment variable references, and writes out the result. I'll assume you have this available; on Alpine-based images you can do similar tricks with sed(1) (though escaping around the cron schedule will become tricky).
This makes the entrypoint wrapper script something like:
#!/bin/sh
# entrypoint.sh
# Set a default schedule, if the user didn't provide one
if [ -z "$CRON_SCHEDULE" ]; then
export CRON_SCHEDULE='*/10 * * * *'
fi
# Run substitutions on the template file and inject the crontab
envsubst < /app/myjobtime.cron.tmpl | crontab
# Run the main container command
exec "$#"
Since the template isn't a "normal" crontab, it can't go in the "normal" crontab directory; putting it in the application directory is fine. That file has an environment variable reference where the schedule would go
# myjobtime.cron.tmpl
${CRON_SCHEDULE} /app/myscript.py
In your image, set the wrapper script to be the ENTRYPOINT, make sure the template file is in the right place, and leave the CMD unchanged.
# (assuming there's not a broad `COPY . .`)
COPY myjobtime.cron.tmpl .
COPY entrypoint.sh .
ENTRYPOINT ["/app/entrypoint.sh"] # must be JSON-array syntax
CMD cron # unchanged
This should allow you to override the cron schedule.
docker run -d --name hourly myappcron
docker run -d --name daily -e 'CRON_SCHEDULE=0 0 * * *' myappcron
Since the entrypoint wrapper script runs whatever command was provided, and you can override the command pretty easily, this also lets you double-check that the right schedule got set.
docker run --rm -e 'CRON_SCHEDULE=0 0 * * *' myappcron \
crontab -l # runs instead of the cron daemon

Crontab task doesn't work when I edit crontab by vim instead of "crontab -e" on docker container ubuntu18.04

Crontab task doesn't work when I edit crontab by vim instead of "crontab -e" on docker container ubuntu18.04
step 1:
Use docker run a container, the image is ubuntu18.04 os.
step 2:
vim /var/spool/cron/crontabs/root
and Write content to root file as following:
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
*/1 * * * * . /etc/profile; /bin/sh /test_cron/xx.sh 2>&1
step 3:
cd /
mkdir test_cron
cd test_cron
step 4:
Edit xx.sh in /test_cron/xx.sh, the content as following:
echo "cron job has start" >> /test_cron/run.log
step 5:
service cron restart
step 6:
There is no run.log in /test_cron/, that’s to say, the crontab task doesn't work. But if I using "crontab -e" to open the /var/spool/cron/crontabs/root file and don't make anything modify. Just open and close the /var/spool/cron/crontabs/root, I can see the run.log file in /test_cron/, amazing, the crontab task worked. Could you tell me the reason?
Few points,
The corntab -e makes sure certain formatting and error tracking to an extent.
crontab file should contain one empty line at the end.
There are certain permission to set to the crontab chmod 600
After completing these I could see the manual entry was working. However it is not recommended to directly edit the crontab file and the best practice is to use crontab -e
EDIT: Actually emptyline should be corrected as newline character or % as per the man page
The "sixth" field (the rest of the line) specifies the command to be
run. The entire command portion of the line, up to a newline or %
character, will be executed by /bin/sh or by the shell specified in
the SHELL variable of the cronfile. Percent-signs (%) in the command,
unless escaped with backslash (), will be changed into newline
characters, and all data after the first % will be sent to the command
as standard input.

Cron task inside container from host

I am trying a cron task inside a container from host but with no luck. From the host I am adding the following line on crontab -e
* * * * * docker exec -it sample_container bash -c 'touch /selected/directory/temp$(date +%H-%M)'
But this is not working. Interestingly, when I run the command independently outside crontab it is successfully executing. Can anyone explain what am I missing here?
Note: when debugging such problems with cron, you should look for errors in your local system mails or redirect those to your real mail by adding MAILTO=yourmail#yourdomain.com on top of your crontab file.
There are 2 problems with your crontab command
TLDR; the fixed cron expression
* * * * * docker exec sample_container bash -c 'touch /selected/directory/temp$(date +\%H-\%M)'
% has a special meaning in crontab
From man -s 5 crontab
Percent-signs (%) in the command, unless escaped with backslash (\),
will be changed into newline characters, and all data after the
first % will be sent to the command as standard input.
So you will need to escape those % signs in your date format string
Cron does not allocate a tty
Cron does not allocate a tty whereas your are trying to use one when executing your command (i.e. the -t option to docker exec). The command will therefore fail with the error the input device is not a TTY
You do not need to go interactive (-i) nor to allocate a tty for this command to do its job anyway, so you have to drop those options to launch it from cron.

Custom shell script in crontab

I've a simple shell script that executes a docker-exec command inside a container.
The script is located in /var/www/mysite-nginx/nginx-reload.sh and permissions of this file are -rwxrwxr-x
#!/bin/sh
docker exec -it mysite_nginx nginx -s reload
If I execute this script directly from shell, it works. But if I add the script to my crontab with the following line, it doesn't work.
15 4 * * * /var/www/mysite-nginx/nginx-reload.sh
I suppose that cron doesn't execute the command, or what is wrong?
On /var/log/syslog I have:
Jul 23 15:30:01 arrubiu CRON[29511]: (sergej) CMD (/var/www/mysite-nginx/nginx-reload.sh)
[EDIT] Solved in this way: docker exec is not working in cron
The issue seems to be that docker is not found. There are two ways around:
You enter the full paths of all application in your crontab script, you can find that out using e.g. locate docker, so that it looks something like
#!/bin/sh
/usr/bin/docker exec -it mysite_nginx
/usr/bin/nginx -s reload
Alternatively, you can set the $PATH and other environment variables in the same way how they are set for a usual sh-script. To achieve that, first backup what is saved in /etc/environment, and then flush it with the currently available variables by executing:
cp /etc/environment > ~/my_etc_environment_backup
env >> /etc/environment
Related questions on SO
Where can I set environment variables that crontab will use?

Running cron in a docker container on a windows host

I am having some problems trying to make a container that runs a cronjob. I can see cron running using top in the container but it doesn't write to the log file as the below example attempts to. The file stays empty.
I have read answers to the same question here:
How to run a cron job inside a docker container?
Output of `tail -f` at the end of a docker CMD is not showing
But I could not make any of the suggestions work. For example I used the dockerfile from here: https://github.com/Ekito/docker-cron/
FROM ubuntu:latest
MAINTAINER docker#ekito.fr
# Add crontab file in the cron directory
ADD crontab /etc/cron.d/hello-cron
# Give execution rights on the cron job
RUN chmod 0644 /etc/cron.d/hello-cron
# Create the log file to be able to run tail
RUN touch /var/log/cron.log
#Install Cron
RUN apt-get update
RUN apt-get -y install cron
# Run the command on container startup
CMD cron && tail -f /var/log/cron.log
crontab:
* * * * * root echo "Hello world" >> /var/log/cron.log 2>&1
# Don't remove the empty line at the end of this file. It is required to run the cron job
It didn't work on my machine (windows 10). Apparently there seems to be a windows specific issue also reported by someone else: https://github.com/Ekito/docker-cron/issues/3
To test if it was just me doing something wrong I tried to do the same in a virtual machine running ubuntu (so an ubuntu host instead of my windows host) and that worked as expected. The log file is extended as expected.
So what can I do to try to make this work?
I tried writing to a mounted (bind) folder and making a volume to write to. Neither worked.
rferalli's answer on the github issue did the trick for me:
"Had the same issue. Fixed it by changing line ending of the crontab file from CRLF to LF. Hope this helps!"
I have this problem too.
My workaround is to use Task Scheduler to run a .bat file that start a container instead
Using Task Scheduler: https://active-directory-wp.com/docs/Usage/How_to_add_a_cron_job_on_Windows.html
hello.bat
docker run hello-world
TaskScheduler Action
cmd /c hello.bat >> hello.log 2>&1
Hope this help :)

Resources