I would like to run a bash script periodically inside a Docker container (my work is based on this answer: https://stackoverflow.com/a/37458519/6240756)
Here is my script hello.sh:
#!/bin/sh
echo "Hello world" >> /var/log/cron.log 2>&1
Here is the cron file hello-cron:
# m h dom mon dow command
* * * * * /app/hello.sh
# Empty line
And here is my Dockerfile:
FROM ubuntu:20.04
RUN apt-get update && apt-get install -y cron
# Add backup script
COPY hello.sh /app/
RUN chmod +x /app/hello.sh
# Configure the cron
# Copy file to the cron.d directory
COPY hello-cron /etc/cron.d/hello-cron
# Give execution rights on the cron job
RUN chmod 0644 /etc/cron.d/hello-cron
# Apply cron job
RUN crontab /etc/cron.d/hello-cron
# Create the log file to be able to run tail
RUN touch /var/log/cron.log
# Start the cron
CMD cron && tail -f /var/log/cron.log
I build and run the container but nothing happens. I should see "Hello world" displayed every minutes.
If I replace the call to the script in the cron file by directly echo "Hello world" >> /var/log/cron.log 2>&1 it works, I see "Hello world" every minutes
What am I doing wrong?
EDIT
And the Docker commands:
docker build -t hello-cron .
docker run -t -i hello-cron
About your concrete question
The problem is that you're launching your docker with -t -i, and what you want is a background execution and check it interactively.
Try with:
docker run -d --name mycontainer hello-cron
docker logs -f mycontainer
Best practices
If you are going to execute something periodically, consider if it should be in healthcheck definition, where you can set period and other variables.
Second, note that your cron.log is not mounted, so, you'd lose this info if docker restart.
For a daily database backup, I created the following cron job :
File : crontab -e
SHELL=/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin
* * * * * /bin/bash /var/path/deploy/database/scripts/backup.sh
File : /var/path/deploy/database/scripts/backup.sh
#!/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
cp -r /var/path/deploy/database/scripts /var/bricoolpathpostgresql/data
chmod 755 -R /var/path/postgresql/data
docker exec -it database /var/lib/postgresql/data/scripts/pg_backup_rotated.sh
When I execute the script directly it works well and the backup is created successfully. But the script is being excuted from the cron job the command docker exec -it database /var/lib/postgresql/data/scripts/pg_backup_rotated.sh does not seem to work.
I have no error output in /var/log/syslog
as Danny Ebbers mentioned in comment, the problem ws the -i argument in Docker command.
I have a shell script, it is not executing the "crontab" command when it is run from docker CMD. But works when I execute the file inside the docker container. What am I missing?
File entry.sh:
#!/bin/sh
echo "Starting cron"
/usr/sbin/cron -f -L 15
crontab /etc/cron.d/cron-python
Docker file:
FROM python:3
RUN apt-get update && apt-get -y install cron
COPY ./cron/entry.sh /entry.sh
COPY ./cron/crontab.txt /etc/cron.d/cron-python
RUN chmod +x /entry.sh
RUN chmod 0644 /etc/cron.d/cron-python
CMD ["./entry.sh"]
cron-python:
# crontab -e
*/1 * * * * python /app/myscript.py >> /var/log/script.log 2>&1
Following should work :
#!/bin/sh
# start cron
echo "Starting cron"
crontab /etc/cron.d/cron-python
/usr/sbin/cron -f -L 15
In your version, /etc/cron.d/cron-python does not get installed as you asked /usr/sbin/cron to run on foreground.
Also you need to copy /app/myscript.py.
I have created one test.sh shell script which I have scheduled using crontab -e to execute after every 1 minutes and redirecting output to a file.
test.sh
echo "Printing all Environment Var"
env
echo "Bye Bye"
Below is how my crontab look like
#crontab
0,1,2,3,4,5,6,7,8,9,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59 * * * * sudo su - admiir -c /u01/users/admiir/test.sh > /u01/app/iir/InformaticaIR/iirlog/crontab_launchsh.log
When I run ls -ltr the timestamp is getting updated but nothing is getting printed in the output file.
To run the cron every minute and to save to a file the current environment used this could be used:
* * * * * env > ~/cronenv
Next, you can start a shell like it will be run within cron by doing:
env - `cat ~/cronenv` /bin/sh
Here you could try something like:
su - admiir -c "/u01/users/admiir/test.sh > /u01/app/iir/InformaticaIR/iirlog/crontab_launchsh.log"
You can omit the sudo su and only use su
Once your script is working you could then update your cron with:
* * * * * su - admiir -c "/path/to/test.sh > /path/to/out.txt"
You could also run the cron as the specific user by doing:
sudo crontab -u username -e
I'm trying to run a sh script from crontab. If I run script manually it works perfect, but when I run it in crontab, I get errors.
The script:
#!/bin/bash
sudo tar -zcvf /var/www/nextcloud/data/nextcloud/files/backup.tar.gz /home/beno/stuff/
sudo -u www-data /usr/bin/php /var/www/nextcloud/occ file:scan --all >> /var/www/nextcloud/data/nextcloud/files/backup_log.txt
The script is supposed to make a tar backup of a folder and put it in nextcloud folder and run command files:scan, so nextcloud rescans filesystem and starts synchronization...as I read it here:
https://doc.owncloud.org/server/9.0/admin_manual/configuration_server/occ_command.html#file-operations-label
When crontab runs the script, backup.tar.gz is created, then I get following error:
An unhandled exception has been thrown:
Doctrine\DBAL\DBALException: Failed to connect to the database: An exception occured in driver: SQLSTATE[HY000] [2002] No such file or directory in /var/www/nextcloud/lib/private/DB/Connection.php:60
I'm using ubuntu16 and nextcloud11. Please help!
Following you'r request
Instead of using you'r own crontab, you have to use specic user's crontab, by sudo your crontab command:
sudo -s
then
crontab -e
now you coul add the root's 1st line:
tar -zcvf /var/www/nextcloud/data/nextcloud/files/backup.tar.gz /home/beno/stuff/
and once finished
exit
sudo -s www-data
... and so on...
or (if you could'nt run a shell under www-data):
sudo www-data crontab <<<'01 2 * * * /usr/bin/php /var/www...'
Note: This will overwrite www-data's crontab by this only line!
To prevent this, you could:
sudo www-data crontab -l
to see what contain actual crontab, then
sudo www-data crontab -l |
sed -e '$a 01 2 * * * /usr/bin/php /var/www...'
For adding you'r line, and finally
sudo www-data crontab -l |
sed -e '$a 01 2 * * * /usr/bin/php /var/www...' |
sudo www-data crontab
For replacing actual crontab by modified one.
But it could be simplier to
sudo vi /etc/cron.d/mybackups
Then add you'r rule by following time spec by user name:
21 22 * * * root tar -zcvf /var/w...
22 23 * * * www-data /usr/bin/php /var/www...
Further doc
see man -P'less +/SYSTEM' 5 crontab