У мене зазвичай є кілька проблем з тим, як cron виконує сценарії, оскільки вони, як правило, не встановлюють моє середовище. Чи є спосіб викликати bash (?) Таким же чином, як це робить cron, щоб я міг перевірити скрипти перед їх встановленням?
У мене зазвичай є кілька проблем з тим, як cron виконує сценарії, оскільки вони, як правило, не встановлюють моє середовище. Чи є спосіб викликати bash (?) Таким же чином, як це робить cron, щоб я міг перевірити скрипти перед їх встановленням?
Відповіді:
Додайте це до свого кронт (тимчасово):
* * * * * env > ~/cronenv
Після запуску зробіть це:
env - `cat ~/cronenv` /bin/sh
Це передбачає, що ваш cron працює / bin / sh, що є типовим, незалежно від оболонки користувача за замовчуванням.
env -
кішка ~ / cronenv` / bin / sh` також повинна бути записана як робота з кроном? будь ласка, наведіть приклад
Cron надає лише це середовище за замовчуванням:
HOME
домашній каталог користувачаLOGNAME
логін користувачаPATH=/usr/bin:/usr/sbin
SHELL=/usr/bin/sh
Якщо вам потрібно більше, ви можете надсилати скрипт, де ви визначаєте своє оточення перед таблицею планування в crontab.
Пара підходів:
Експорт cron env та джерело його:
Додайте
* * * * * env > ~/cronenv
до свого кронтабу, нехай він працює один раз, вимкніть його, а потім запустіть
env - `cat ~/cronenv` /bin/sh
А ви зараз перебуваєте в sh
сесії, в якій є середовище cron
Піднесіть своє оточення до крону
Ви можете пропустити вище вправи і просто зробити . ~/.profile
перед вашою роботою з крона, наприклад
* * * * * . ~/.profile; your_command
Використовувати екран
Наведені вище рішення все ще не спрацьовують, оскільки вони забезпечують середовище, підключене до запущеного сеансу X, з доступом до dbus
тощо. Наприклад, на Ubuntu nmcli
(Менеджер мереж) буде працювати вище двох підходів, але все ще виходить з ладу в cron.
* * * * * /usr/bin/screen -dm
Додайте вище крон до рядка, нехай він працює один раз, вимкніть його. Підключіться до екранного сеансу (екран -r). Якщо ви перевіряєте, що створений сеанс екрана (з ps
), пам’ятайте, що вони іноді знаходяться у великих літерах (наприклад ps | grep SCREEN
)
Зараз навіть nmcli
і подібне не вдасться.
Ви можете запустити:
env - your_command arguments
Це запустить ваш_команда з порожнім середовищем.
env - HOME="$HOME" LOGNAME="$USER" PATH="/usr/bin:/bin" SHELL="$(which sh)" command arguments
що, здається, робить трюк
Залежно від оболонки рахунку
sudo su
env -i /bin/sh
або
sudo su
env -i /bin/bash --noprofile --norc
Від http://matthew.mceachen.us/blog/howto-simulate-the-cron-environment-1018.html
Відповідь через шість років: проблема невідповідності середовища є однією з проблем, яку systemd
"таймери" вирішують як заміну крона. Незалежно від того, запускаєте ви системну "службу" від CLI або через cron, вона отримує абсолютно те саме середовище, уникаючи проблеми невідповідності оточення.
Найпоширенішою проблемою, яка може призвести до виходу з ладу завдань cron, коли вони проходять вручну, є обмежувальний за замовчуванням, $PATH
встановлений cron, що це в Ubuntu 16.04:
"/usr/bin:/bin"
На відміну від цього , за замовчуванням $PATH
встановлений systemd
на Ubuntu 16.04 є:
"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
Тож вже є більший шанс, що системний таймер знайде бінарний файл без зайвих клопотів.
Мінус системних таймерів - це трохи більше часу, щоб їх налаштувати. Ви спочатку створюєте "службовий" файл, щоб визначити, що ви хочете запустити, і "таймер", щоб визначити графік його запуску і, нарешті, "включити" таймер для його активації.
Створіть завдання cron, яке виконує env та перенаправляє stdout у файл. Використовуйте файл поряд із "env -", щоб створити таке ж середовище, що і завдання cron.
Не забувайте, що оскільки батько cron є init, він запускає програми без керуючого терміналу. Ви можете імітувати це за допомогою такого інструменту:
За замовчуванням cron
виконує свої завдання, використовуючи будь-яку ідею вашої системи sh
. Це може бути фактичним Борна оболонка або dash
, ash
, ksh
або bash
(або інший) слінковано в sh
(і , як наслідок , що працює в режимі POSIX).
Найкраще зробити, щоб переконатися, що у ваших сценаріях є те, що їм потрібно, і припустити, що їм нічого не передбачено. Тому вам слід використовувати повні специфікації каталогів та встановлювати змінні середовища, наприклад, $PATH
ви самі.
0 0 * * 1 /path/to/executable >/dev/null 2>&1
а потім, у межах "виконуваного файлу", я встановив би значення для $PATH
тощо, і використовував повні специфікації каталогів для введення та виводу файлів тощо. Наприклад:/path/to/do_something /another/path/input_file /another/path/to/output_file
Ще один простий спосіб, який я знайшов (але може бути схильним до помилок, я все ще тестую) - це джерело файлів профілю вашого користувача перед вашою командою.
Редагування сценарію /etc/cron.d/:
* * * * * user1 comand-that-needs-env-vars
Перетвориться на:
* * * * * user1 source ~/.bash_profile; source ~/.bashrc; comand-that-needs-env-vars
Брудно, але це зробило роботу для мене. Чи є спосіб імітувати логін? Просто команду, яку ти міг би виконати?bash --login
не працювало. Це здається, що це був би кращий шлях.
EDIT: Це, здається, є надійним рішенням: http://www.epicserve.com/blog/2012/feb/7/my-notes-cron-directory-etccrond-ubuntu-1110/
* * * * * root su --session-command="comand-that-needs-env-vars" user1 -l
Прийнята відповідь дає спосіб запустити сценарій із середовищем cron. Як зазначали інші, це не єдиний необхідний критерій для налагодження робочих записів у системі.
Дійсно, cron також використовує неінтерактивний термінал, без вкладеного вводу тощо.
Якщо це допомагає, я написав сценарій, який дозволяє безболісно виконувати команду / сценарій, як це було б запущено cron. Викликайте це своєю командою / сценарієм як перший аргумент, і ви добре.
Цей сценарій також розміщений (і можливо оновлений) на Github .
#!/bin/bash
# Run as if it was called from cron, that is to say:
# * with a modified environment
# * with a specific shell, which may or may not be bash
# * without an attached input terminal
# * in a non-interactive shell
function usage(){
echo "$0 - Run a script or a command as it would be in a cron job, then display its output"
echo "Usage:"
echo " $0 [command | script]"
}
if [ "$1" == "-h" -o "$1" == "--help" ]; then
usage
exit 0
fi
if [ $(whoami) != "root" ]; then
echo "Only root is supported at the moment"
exit 1
fi
# This file should contain the cron environment.
cron_env="/root/cron-env"
if [ ! -f "$cron_env" ]; then
echo "Unable to find $cron_env"
echo "To generate it, run \"/usr/bin/env > /root/cron-env\" as a cron job"
exit 0
fi
# It will be a nightmare to expand "$@" inside a shell -c argument.
# Let's rather generate a string where we manually expand-and-quote the arguments
env_string="/usr/bin/env -i "
for envi in $(cat "$cron_env"); do
env_string="${env_string} $envi "
done
cmd_string=""
for arg in "$@"; do
cmd_string="${cmd_string} \"${arg}\" "
done
# Which shell should we use?
the_shell=$(grep -E "^SHELL=" /root/cron-env | sed 's/SHELL=//')
echo "Running with $the_shell the following command: $cmd_string"
# Let's route the output in a file
# and do not provide any input (so that the command is executed without an attached terminal)
so=$(mktemp "/tmp/fakecron.out.XXXX")
se=$(mktemp "/tmp/fakecron.err.XXXX")
"$the_shell" -c "$env_string $cmd_string" >"$so" 2>"$se" < /dev/null
echo -e "Done. Here is \033[1mstdout\033[0m:"
cat "$so"
echo -e "Done. Here is \033[1mstderr\033[0m:"
cat "$se"
rm "$so" "$se"
Відповідь https://stackoverflow.com/a/2546509/5593430 показує, як отримати середовище cron і використовувати його для свого сценарію. Але майте на увазі, що середовище може відрізнятися залежно від файлу crontab, який ви використовуєте. Я створив три різні записи в cron, щоб врятувати середовище через env > log
. Це результати на Amazon Linux 4.4.35-33.55.amzn1.x86_64.
MAILTO=root
SHELL=/bin/bash
USER=root
PATH=/sbin:/bin:/usr/sbin:/usr/bin
PWD=/
LANG=en_US.UTF-8
SHLVL=1
HOME=/
LOGNAME=root
_=/bin/env
crontab -e
)SHELL=/bin/sh
USER=root
PATH=/usr/bin:/bin
PWD=/root
LANG=en_US.UTF-8
SHLVL=1
HOME=/root
LOGNAME=root
_=/usr/bin/env
MAILTO=root
SHELL=/bin/bash
USER=root
PATH=/sbin:/bin:/usr/sbin:/usr/bin
_=/bin/env
PWD=/
LANG=en_US.UTF-8
SHLVL=3
HOME=/
LOGNAME=root
Найголовніше PATH
, PWD
і HOME
відрізняються. Обов’язково встановіть їх у своїх сценаріях cron, щоб покладатися на стабільне середовище.
Я не вірю, що існує; Єдиний спосіб, який я знаю, щоб перевірити роботу з крон - це налаштувати його на майбутнє хвилину чи дві, а потім чекати.