cron: Permission denied

После обновления на openSUSE 11.2 перестали запускаться некоторые задачи cron'а. Описаны они были в отдельном файле, расположенном в /etc/cron.d и запускаться должны быть не от root, а от некоторого системного пользователя. Но вместо выполнения, в /var/log/messages обнаружились только записи вида "/usr/sbin/cron[47852]: Permission denied".

Ошибка, прямо скажем, не очень информативного содержания. openSUSE использует vixie-cron, снабженный дополнительными патчами, один из которых обеспечивает работу с PAM. В пакете идет так-же и файл /etc/pam.d/crond с настройками.

Исполнению скрипта мешал модуль pam_unix2.so(разработанный Thorsten Kukuk), т.к. этот модуль новой версии считает, что аккаунт заблокирован, если в файле /etc/shadow на месте пароля записан символ '!'. По некоторому стечению обстоятельств так и оказалось. Еще туда можно записать '*', как говорится, почувствуйте разницу.

"Argument list too long"

Какое количество аргументов можно запихнуть в командную строку? Как хорошо известно, исполнение новой программы запускается той или иной вариацией функции exec. А функции эти иногда могут возвращать ошибку E2BIG. Дословно процитировав man, можно было бы воскликнуть: "The total number of bytes in the environment (envp) and argument list (argv) is too large."

В Linux константа ARG_MAX определена в файле include/linux/limits.h, где так и написано 131072 байтов (это на переменные окружения и аргументы командной строки вместе).

Где-то между 2.6.22 и 2.6.23 ситуация немного изменилась, посмотрев в функцию get_arg_page(), что в файле fs/exec.c, можно заметить, что теперь размер ограничен четвертью стека, и, следовательно, может быть неограничен вовсе, т.к. размер стека может быть изменен перед запуском процесса, используя команду ulimit -s.

Простенький скрипт позволяющий поиграть с размером области для аргументов. Будет работать только на системах с ядрами новее, чем 2.6.23. На более старых всегда будет один и тот же результат — 131072.
#!/bin/sh

EXEBIN=/bin/true

pattern=$(perl -e 'print ("x" x 4095)."\n";')

ulimit -s $1
ulimit -s

arg=$pattern
while $EXEBIN $arg
do
        echo -n .
        arg="$arg $pattern"
done

echo $? ${#arg}

Обновление на openSUSE 11.2.

Сегодня успешно обновил openSUSE 11.1 до openSUSE 11.2 прямо на ходу, с помощью zypper dup. Процесс от начала обновления, до начала написания заметки в блоге занял ровно четыре часа.

Восемь шагов к совершенству:
  1. zypper mr -a -d
  2. zypper ar http://download.opensuse.org/distribution/11.2/repo/non-oss/ openSUSE-11.2-non-oss
  3. zypper ar http://download.opensuse.org/distribution/11.2/repo/oss/ openSUSE-11.2-oss
  4. zypper ar -f http://download.opensuse.org/update/11.2/ openSUSE-11.2-updates
  5. zypper refresh
  6. zypper in zypper
  7. zypper dup
  8. SuSEconfig

Замечу лишь, что при попытке сделать zypper in zypper было обновлено несколько пакетов, и после этого система оказалась в некоторой некондиции. Сначала я пробовал сделайть апдейт используя DVD, но dup сказал: "/bin/mount: error while loading shared libraries: libvolume_id.so.1: cannot open shared object file: No such file or directory". Поэтому нужно заранее позаботиться о наличии статически слинкованного mount в нужном месте, если необходимо использование DVD.

Новый zypper обладает параметром commit.downloadMode в конфигурационном файле /etc/zypp/zypp.conf. Его можно установить в позицию DownloadInAdvance, если существует недоверие к надежности используемого инетрнет-канала. Это заставит zypper сначала скачать все пакеты, затем их установить.

Все запущенные программы вместе с kde продолжали выполнятся в течение всего процесса обновления, но при попытке выйти из kde после успешного апгрейда упала парочка программ, запустив окна отчета об ошибке.