- Systemd, интерактивные скрипты и таймеры
- Введение
- Зачем нужны target
- Пример target при включении(обзор возможности) с запуском интерактивного скрипта
- Подготовка прошивки к запуску
- Сервис с таймером для logrotate
- Интерактивный скрипт при выключении и свой таргет выключения
- One Time Task Scheduling using at Command in Linux
- Commands used with at:
- 1. Schedule first job using at command
- 2. List the scheduled jobs using atq
- 3. Remove scheduled job using atrm
- 4. Check the content of scheduled at job
- Examples of at Command:
- Related Posts
- How to Scan Open Ports with Nmap
- Handling filenames with spaces in Linux
- How To Compare Two Files in Linux
- 29 Comments
Systemd, интерактивные скрипты и таймеры
Введение
При разработке под linux возникают задачи создания интерактивных скриптов, выполняемых при включении или завершении работы системы. В system V это делалось легко, но с systemd вносит коррективы. Зато оно умеет свои таймеры.
Зачем нужны target
Часто пишут, что target служат аналогом runlevel в system V -init. В корне не согласен. Их больше и можно разделять пакеты по группам и, к примеру, запускать одной командой группу сервисов, выполнять дополнительные действия. Кроме того, у них нет иерархии, только зависимости.
Пример target при включении(обзор возможности) с запуском интерактивного скрипта
Описание самого target:
Данный target запустится, когда будет запущен multi-user.target и вызовет installer.service. При этом таких сервисов может быть несколько.
И наконец, пример выполняемого скрипта:
Самое главное — выбрать final.target — target, к которому система должна придти при запуске. В процессе запуска systemd пройдёт по зависимостям и запустит всё нужное.
Выбрать final.target можно разными способами, я использовал для этого опцию загрузчика.
Итоговый запуск выглядит так:
- Стартует загрузчик
- Загрузчик начинает запуск прошивки, передавая параметр final.target
- Systemd начинает запуск системы. Последовательно идёт к installer.target или work.target от basic.target через их зависимости (например,multi-user.target). Последние и приводят систему к работе в нужном режиме
Подготовка прошивки к запуску
При создании прошивок всегда возникает задача восстановления состояния системы при старте и его сохранении при выключении. Под состоянием подразумеваются конфигурационные файлы, дампы базы данных, настройки интерфейсов и тд.
Systemd запускает процессу в одном таргете параллельно. Есть зависимости, которые позволяют определить последовательность запуска скриптов.
- Система стартует
- Запускается сервис settings_restore.service.Он проверяет наличие файла settings.txt в разделе с данными. Если его нет, то на его место кладётся эталонный файл.Далее происходит восстановление настроек системы:
- пароля администратора
- hostname,
- часового пояс
- локаль
- Определение, весь ли носитель используется. По умолчанию размер образа небольшой — для удобства копирования и записи на носитель. При старте проверяется — есть ли ещё неиспользуемое место. Если есть — диск переразбивается.
- Генерация machine-id из MAC-адреса. Это важно для получения одного и того же адреса по DHCP
- Настройки сети
- Ограничивается размер логов
- Подготавливается к работа внешний диск(если включена соответствующая опция и диск новый)
- Запускаться postgresq
- запускается сервис restore. Он нужен для подготовки самого zabbix и его базы данных:
- Проверяется, есть ли уже база данных zabbix. Если нет — создается из инициализирующих дампов(идут в поставке zabbix)
- создается список часовых поясов (нужно для их отображения в web-интерфейсе)
- Находится текущий IP, он выводится в issue (приглашение для входа в консоли)
- Меняется приглашение — появляется фраза Ready to work
- Прошивка готова к работе
Важны файлы сервисов, именно они выставляют последовательность их запуска
Как видно, я поставил зависимости, что бы сначала отработал мой скрипт, а только потом поднималась сеть и стартовала СУБД.
И второй сервис(подготовка zabbix)
Здесь немного сложнее.Запуск так же в multi-user.target, но ПОСЛЕ запуска СУБД postgresql и моего setting_restore. Но ПЕРЕД запуском служб zabbix.
Сервис с таймером для logrotate
Systemd может заменить CRON. Серьезно. Причем точность не до минуты, а до секунды(а вдруг понадобится).А можно создать монотонный таймер, вызываемый по таймауту от события.
Именно монотонный таймер, считающий время от запуска машины, я и создал.
Для этого потребуется 2 файла
logrotateTimer.service — собственно описание сервиса:
Всё просто — описание команда запуска.
Второй файл logrotateTimer.timer — вот он и задает работу таймеров:
- описание таймера
- Время первого запуска, начиная от загрузки систем
- период дальнейших запусков
- Зависимость от службы таймеров.Фактически, это строка и делает таймер
Интерактивный скрипт при выключении и свой таргет выключения
В другой разработке мне пришлось делать более сложный вариант выключения машины — через собственный таргет, что бы выполнить множество действий. Обычно рекомендуется создать сервис oneshot с опцией RemainAfterExit, но это не дает создать интерактивный скрипт.
А дело в том, что команды, запускаемые опцией ExecOnStop выполняются вне TTY! Проверить просто — вставьте команду tty и сохраните её вывод.
Поэтому я реализовал выключение через свой таргет. На 100% правильность не претендую, но это работает!
Как это делалось(в общих чертах):
Создал таргет my_shutdown.target, который ни от кого не зависел:
my_shutdown.target
При переходе в этот таргет(через systemctl isolate my_shutdwn.target), он запускал сервис my_shutdown.service, задача которого простая — выполнить скрипт my_shutdown.sh:
- Внутри этого скрипта я выполняю нужные действия. Можно в таргет добавить много скриптов, для гибкости и удобства:
Примечание. Использование файлов /tmp/reboot и /tmp/shutdown. Нельзя вызвать target с параметрами. Можно только service.
Но я использую target, что бы иметь гибкость в работе и гарантированный порядок выполнения действий.
Однако, самое интересное было потом. Машину же надо выключить/перезагрузить. И тут есть 2 варианта:
- Заменить команды reboot,shutdown и прочие(они все равно являются симлинками на systemctl) на свой скрипт.Внутри скрипта — переход в my_shutdown.target. А скрипты внутри таргета потом вызывают напрямую systemctl, например, systemctl reboot
- Более простой, но мне не нравящийся вариант. Во всех интерфейсах вызывать не shutdown/reboot/прочие, а напрямую вызывать таргет systemctl isolate my_shutdown.target
Я выбрал первый вариант. В systemd reboot(как и poweroff) являются симлинками на systemd.
Поэтому их можно заменить на свои скрипты:
reboot
Источник
One Time Task Scheduling using at Command in Linux
While working with Linux systems we preferred crontab for scheduling jobs generally. There are another utility at command is very useful for scheduling one time tasks. It reads commands from standard input or script/file which can be executed later once. But we can’t use at command for any recurring tasks. For recurring tasks use Linux crontab.
At command can be useful for shutdown system at the specified time, Taking a one-time backup, sending email as a reminder at the specified time etc. This article will help you to understand the working of at command with useful examples.
Commands used with at:
- at : execute commands at specified time.
- atq : lists the pending jobs of users.
- atrm : delete jobs by their job number.
1. Schedule first job using at command
Below example will schedule “sh backup.sh” command to be executed on next 9:00 AM once.
Use ^d to exit from at prompt.
You can also use the following option to schedule a job. The below command will run “sh backup.sh” at 9:00 in the morning.
2. List the scheduled jobs using atq
When we list jobs by root account using atq , it shows all users jobs in the result. But if we execute it from a non-root account, it will show only that users jobs.
Fields description:
First filed: job id
Second filed: Job execution date
third filed: Job execution time
Last field: User name, under which job is scheduled.
3. Remove scheduled job using atrm
You can remove any at job using atrm with their job id.
4. Check the content of scheduled at job
atq command only shows the list of jobs but if you want to check what script/commands are scheduled with that task, below example will help you.
In the above example, 5 is the job id.
Examples of at Command:
1. Schedule task at coming 10:00 AM.
2. Schedule task at 10:00 AM on coming Sunday.
3. Schedule task at 10:00 AM on coming 25’th July.
4. Schedule task at 10:00 AM on coming 22’nd June 2015.
5. Schedule task at 10:00 AM on the same date at next month.
6. Schedule task at 10:00 AM tomorrow.
7. Schedule task at 10:00 AM tomorrow.
8. Schedule task to execute just after 1 hour.
9. Schedule task to execute just after 30 minutes.
10. Schedule task to execute just after 1 and 2 weeks.
11. Schedule task to execute just after 1 and 2 years.
12. Schedule task to execute at midnight.
The above job will execute on next 12:00 AM
Thanks for reading this article, I hope you will understand how to use ‘at’ command in Linux.
Related Posts
How to Scan Open Ports with Nmap
Handling filenames with spaces in Linux
How To Compare Two Files in Linux
29 Comments
EXACTLY WHAT I NEEDED.
BTW the recaptcha input is underneath the Submit button in the comments form. Hard to click.
Thanks Khay, I hope recaptcha positioned correctly now.
Hi,
does it generate log after execution like cron ?
How can we schedule a gtk “graphical” job, for example a simple yad message?
yad –title “Warning” –text “Alarm now, attention” –on-top –borders=25
In my tests, no display is shown at a specified time.
How is it better to schedule installation of upgrades?
For some reason tasks don’t execute. I tried something like: sudo apt-get upgrade -y | at 21:00
It should be
echo “apt-get upgrade -y” | sudo at 21:00
how can we Schedule one job at two different timing with single command
touch helloworld.txt | at now + 1 minute | at now + 2 hours
Where do I see the output ? How will I know if the job has been executed or not ?
please tell me that i want to run a corntab command in every last day of the month.
i am thinking but in some its 30 days and 31 in some and 28 and 29 like that.
You can try cron like this:
here [ “$(date +%d -d tomorrow)” = “01” ] will retrun true if tomorrow is the first day of next month.
I’m using at to run mplayer and stream some radio station, when i want to stop mplayer and use atrm command it doesn’t work. i got only ” Warning: deleting running job” . job vanishes from the atq list, but it still streams music.
HI, I am experiencing an issue. When i am using the format:
command | at time
It is not executing the command that I am providing.
Please tell how to get past it.
echo “command” | at time
Great article Rahul!
I just wanted to extend it a bit with some useful additions.
1) You can use -f option to point “at” to the script you need to run:
at -f /path/to/the/script time_spec
2) One can use “at” to start a process in background without nohup, etc. As easy as
at -f /a/command now
or
echo “/a/command” | at now
3) You can use “at” to run a command repeatedly, but unlike cron you can use “at” to run commands with some period between runs, for example after 3 minutes after previous run was completed. This allow you to avoid various checks preventing next run to start before previous is finished.
Moreover you can define this period as random value. Examples:
The script (lets name it /home/user1/at_run.sh):
————————————-
#!/bin/bash
/the/command/you/need
# fixed period between runs
period=3
# or random period. RANDOM is a bash’s random number from 0 to 32767
period=$[ ($RANDOM % 20) + 15 ]
at -f /home/user1/at_run.sh now + $period minutes
————————————-
run /home/user1/at_run.sh and all next runs will be scheduled automatically, so your /the/command/you/need will run repeatedly forever. Sure, you can break the next run with atq/atrm.
Thx Rahul and Sergey.
@Sergey, in your last point you are basically using a wrapper with a random pause and re-scheduling of the at job.
I think this is also achievable with cron, without the “various checks preventing next run to start before previous is finished”.
You can just replace the last line of your script with this:
sleep $(($period * 60)) && exec /home/user1/at_run.sh
Then set a crontab for /home/user1/at_run.sh .
Note: the ‘exec’ bash builtin will prevent calling bash recursively (nested bash’s) and spare memory.
You will need to kill the process to end it.
If the job is not supposed to stay permanently (boot safe), I would prefer to use an interactive bash inside a ‘screen’ command and just do a loop:
while : ; do
/the/command/you/need
sleep 60
done
So you can follow in “live” the output of the script.
hello!
i am running centos. when i submit an at nothing happens. i can call it up using “atq #”, however, it doesn’t execute?
thanks for the help.
What are the differences between at-command and chrontab?
at command is used for one-time task scheduling. crontab is used for repeated tasks.
I need to run a script at particular time-stamp which internally calls one more script.
But I am getting an error :
at `./radConnect.sh` 09:00
sh: netstat: command not found
sh: /sbin/ifconfig: No such file or directory
Radskman rc:[0] [Request successfully completed]
syntax error. Last token seen: h
Garbled time
Schedule job like following
Hi Rahul,
Thanks for the quick response, the use case which I am trying is a bit different.
I have created some containers using a script and a script internally calls another one which needs to run at a particular timestamp. So the command prompt for giving the script won’t be visible. So is there any alternative to it. Or can we do it using crontab?
Try following command.
What would be the command for future date? midnight on 30 October 2017
echo “sh radConnect.sh” | at ?
i think it should be
echo “sh radConnect.sh” | at 0 0 30 10 * *
this would repeat every year on 30th October.
I think i’ve mixed up with crontab function command.
Correction of the previous command:
echo “sh radConnect.sh” | at 12:00 AM 30.10.17
Hi Nabil.. This will work
Wow that was unusual. I just wrote an incredibly long comment but after I clicked submit my comment didn’t appear. Grrrr… well I’m not writing all that over again. Anyway, just wanted to say fantastic blog!
We are interested as well as enthusiastic about what you really are writing about here.
Источник