crontab -e # редактировать таблицу задач
crontab -l # показать таблицу задач
crontab -r # удалить таблицу задач
crontab path/to/file.crontab # загрузить таблицу задач из файла
打電話時 crontab -e 將使用標準環境變數中指定的編輯器 EDITOR.
任務本身以以下格式描述:
# строки-комментарии игнорируются
#
# задача, выполняемая ежеминутно
* * * * * /path/to/exec -a -b -c
# задача, выполняемая на 10-й минуте каждого часа
10 * * * * /path/to/exec -a -b -c
# задача, выполняемая на 10-й минуте второго часа каждого дня и использующая перенаправление стандартного потока вывода
10 2 * * * /path/to/exec -a -b -c > /tmp/cron-job-output.log
# Запускается ежеминутно по понедельникам и вторникам в январе
* * * Jan Mon,Tue /path/to/exec
您可以指定啟動任務的步驟:
# Запускается с шагом в две минуты
*/2 * * * Mon,Tue /path/to/exec
步驟和間隔可以混合:
# Запускается с шагом в две минуты в первых десять минут каждого часа
0-10/2 * * * * /path/to/exec
支援常用語法的直覺替代方案(重新啟動、每年、每年、每月、每週、每天、午夜、每小時):
# Запускается после перезагрузки системы
@reboot /exec/on/reboot
# Запускается раз в день
@daily /exec/daily
# Запускается раз в час
@hourly /exec/daily
任務執行環境
Vixie cron 允許您更改執行應用程式的環境。
環境變數 USER、LOGNAME 和 HOME 不是簡單地由守護程序提供,而是從檔案中取得 passwd文件。 PATH 變數設定為“/usr/bin:/bin”,SHELL 變數設定為“/bin/sh”。 除了LOGNAME之外的所有變數的值都可以在使用者表中變更。
cron 本身使用一些環境變數(最顯著的是 SHELL 和 HOME)來執行任務。 使用 bash 而不是標準 sh 來執行自訂任務可能如下所示:
SHELL=/bin/bash
HOME=/tmp/
# exec будет запущен bash-ем в /tmp/
* * * * * /path/to/exec
switch (fork()) {
case -1:
/* критическая ошибка и завершение работы */
exit(0);
break;
case 0:
/* дочерний процесс */
(void) setsid();
break;
default:
/* родительский процесс завершает работу */
_exit(0);
}
/* первичная загрузка задач */
load_database(&database);
/* запустить задачи, поставленные к выполнению после перезагрузки системы */
run_reboot_jobs(&database);
/* сделать TargetTime началом ближайшей минуты */
cron_sync();
while (TRUE) {
/* выполнить задачи, после чего спать до TargetTime с поправкой на время, потраченное на задачи */
cron_sleep();
/* перечитать конфигурацию */
load_database(&database);
/* собрать задачи для данной минуты */
cron_tick(&database);
/* перевести TargetTime на начало следующей минуты */
TargetTime += 60;
}
switch (fork()) {
case -1:
/*не смогли выполнить fork */
break;
case 0:
/* дочерний процесс: на всякий случай еще раз пробуем захватить главный лок */
acquire_daemonlock(1);
/* переходим к формированию процесса задачи */
child_process(e, u);
/* по завершению дочерний процесс заканчивает работу */
_exit(OK_EXIT);
break;
default:
/* родительский процесс продолжает работу */
break;
}
switch (vfork()) {
case -1:
/* при ошибки сразу завершается работа */
exit(ERROR_EXIT);
case 0:
/* процесс-внук формирует новую сессию, терминал и т.д.
*/
(void) setsid();
/*
* дальше многословная настройка вывода процесса, опустим для краткости
*/
/* смена директории, пользователя и группы пользователя,
* то есть процесс больше не суперпользовательский
*/
setgid(e->gid);
setuid(e->uid);
chdir(env_get("HOME", e->envp));
/* запуск самой команды
*/
{
/* переменная окружения SHELL указывает на интерпретатор для запуска */
char *shell = env_get("SHELL", e->envp);
/* процесс запускается без передачи окружения родительского процесса,
* то есть именно так, как описано в таблице задач пользователя */
execle(shell, shell, "-c", e->cmd, (char *)0, e->envp);
/* ошибка — и процесс на запустился? завершение работы */
perror("execl");
_exit(ERROR_EXIT);
}
break;
default:
/* сам процесс продолжает работу: ждет завершения работы и вывода */
break;
}