Вероятно, это связано с тем, что переменная окружения DBUS_SESSION_BUS_ADDRESS
не передается в окружение cron.
По крайней мере в Gnome, шина не делается "обнаруживаемой" (как описано в разделе "AUTOMATIC LAUNCHING" раздела dbus-launch(1)
man page) через файлы в $HOME/.dbus/session-bus
. Это оставляет все, что запускается в вашем кронтабе, без возможности обнаружить $DBUS_SESSION_BUS_ADDRESS
и связаться с сессионной D-Bus.
Я поверю вам на слово, что это работало в прошлом, возможно, из-за использования $HOME/. dbus
или существованием реальных файлов /tmp/dbus-$TMPNAM
, на которые ссылается $DBUS_SESSION_BUS_ADDRESS
(который обычно установлен на что-то похожее на unix:abstract=/tmp/dbus-GkJdpPD4sk,guid=0001e69e075e5e2
). Как объясняет dbus-cleanup-sockets(1)
man page:
В Linux эта программа по сути бесполезна, потому что D-Bus по умолчанию к использованию "абстрактных сокетов", которые существуют только в памяти и не имеют соответствующего файла в /tmp.
Однако мы можем использовать вариацию идеи, представленной в сообщении на ubuntuforum, Attach to existing DBUS session over SSH, чтобы обнаружить сессию D-Bus существующей сессии пользователя на локальной машине из среды cron и установить $DBUS_SESSION_BUS_ADDRESS
соответствующим образом.
Хотя используемая там техника обнаруживает окружение из часто запускаемых процессов, таких как nautilus
, pulseaudio
и trackerd
, и требует, чтобы один или несколько из них были запущены в активной сессии, я рекомендую более простой подход.
Все распространенные менеджеры сеансов среды рабочего стола (gnome-session
, lxsession
и kded4
) имеют $DBUS_SESSION_BUS_ADDRESS
, установленный в их среде, даже несмотря на то, что они запускаются до dbus-daemon
и имеют меньшие PID. Таким образом, наиболее разумно просто использовать любой менеджер сессий, соответствующий вашему окружению рабочего стола.
Я написал следующий сценарий, помещенный в $HOME/bin/test-crontab-dbus. sh
, чтобы проверить доступ к существующей шине сессий:
#!/bin/sh
SESSION_MANAGER=lxsession
OUTFILE=/tmp/${USER}-cron-dbus.txt
export $(cat /proc/$(pgrep "$SESSION_MANAGER" -u "$USER")/environ \
|egrep -z '^DBUS_SESSION_BUS_ADDRESS=')
date >> $OUTFILE
dbus-send --session --dest=org.freedesktop.DBus \
/ org.freedesktop.DBus.GetId 2>> $OUTFILE
if test "$?" -eq 0; then
echo "Success contacting session bus!" >> $OUTFILE
fi
Приведенный выше SESSION_MANAGER=lxsession
подходит для основной сессии рабочего стола, запущенной под LXDE, под Gnome вы должны установить SESSION_MANAGER=gnome-session
, а под KDE вы должны использовать SESSION_MANAGER=kded4
.
Если задание в кронтабе имеет доступ к шине сессий, вы увидите на выходе что-то вроде следующего:
Fri Dec 18 15:27:02 EST 2015
Success contacting session bus!
В противном случае вы увидите сообщение об ошибке, выдаваемое dbus-send
.
Очевидно, что вы можете заменить любой другой метод тестирования подключения к сеансовой шине, включая любую операцию, которую вам действительно нужно выполнить через задание cron.
Не существует легко читаемого способа использования DirectoryMatch
для сопоставления всех /var/www/aaa
, /var/www/bbb
и /var/www
, но не /var/www/ccc
. Это связано с тем, что /var/www
включает в себя все остальные три каталога.
Что может быть проще, так это использовать мод _макрос для определения общих разделов конфигурации, а затем применить их с помощью Directory
, как в исходном примере.
a2enmod macro # Enable the mod_macro module
systemctl restart apache2 # YMMV but this is the systemd way
Затем вы можете определить свой макрос. Вот один из них, который я использую
# Logging
#
<Macro CronoLogger $vHost>
ServerSignature On
LogLevel warn
ErrorLog "|/usr/bin/cronolog /home/www/$vHost/logs/%Y/%m/%d/public-error.log"
CustomLog "|/usr/bin/cronolog /home/www/$vHost/logs/%Y/%m/%d/public-access.log" combined
</Macro>
и я включаю его в такое определение виртуального хоста
Use CronoLogger www.contoso.com
В вашем случае с примером макроса StandardStuff param1 param2
вы можете использовать его следующим образом
<Directory /var/www>
Use StandardStuff /var/www /
</Directory>
<Directory /var/www/aaa>
Use StandardStuff /var/www /aaa
</Directory>
<Directory /var/www/bbb>
Use StandardStuff /var/www /bbb
</Directory>
<Directory /var/www/ccc>
# Do non-standard stuff here
#
</Directory>
The manual claims that "within each group the sections are processed in the order they appear in the configuration files", but even if I switch the sections, the result is still the same (that /var/www/ccc is hit by "# lots of stuff" instead of by "# lots of other stuff").
Они оба обрабатываются, поскольку обе директивы совпадают.
Включитеmod_headers
(a2enmod headers
)и попробуйте
<DirectoryMatch /var/www/(aaa|bbb|)>
Header add AAA one
</DirectoryMatch>
<DirectoryMatch /var/www/ccc>
Header add AAA two
</DirectoryMatch>
, и с помощью инструмента разработчика вы увидите, что ответ http://localhost/ccc
содержит оба заголовка.
Если вы хотите сопоставить /var/www
, /var/www/foo.html
, /var/www/aaa
/var/www/aaa/bar
, /var/www/bbb
, /var/www/bbb/baz
, то это должно работать:
<DirectoryMatch ^/var/www/([^/]*|aaa/.*|bbb/.*)$>
[^/]*
соответствует чему-либо внутри /var/www/
, не являющемуся каталогом aaa/.*|bbb/.*
соответствует всему, что находится внутри, включая подкаталоги $
здесь важно, иначе регулярное выражение определяет только начало соответствующего каталога и больше, чем вы хотите Если вам нужно сопоставить только каталоги (и никаких других файлов внутри ), используйте
<DirectoryMatch ^/var/www(/aaa|/bbb)?/?$>
Я, вероятно, предпочел бы LocationMatch
(, если это возможно, ), чтобы вам не приходилось заботиться о структуре каталогов.