Как добавить ~ / bin в PATH для службы systemd?

Я нашел два пути решения этой проблемы. Используйте команду xprop -spy -root _NET_ACTIVE_WINDOW в сочетании с grep в сценарии bash. Создайте C ++ (возможно, C или python, а также мой проект был в C ++ для начала) приложение, использующее библиотеку Xlib для прослушивания событий с X-сервера.

В итоге я использовал альтернативу 1, но я расскажу о них ниже.

Использование xprop: приложение, создающее искомое окно, всегда ставит новое окно сверху и в фокус. Команда xprop -spy позволяет прослушивать изменения в свойствах , а -root - это идентификатор «корневого окна» (R в дереве в вопросе выше). Для прослушивания изменений конкретных свойств мы можем указать имя свойства в этом случае _NET_ACTIVE_WINDOW, которое содержит идентификатор окна, находящегося в настоящее время в фокусе, см. Спецификацию. Затем мы получаем поток вывода следующим образом:

_NET_ACTIVE_WINDOW(WINDOW): window id # 0x3c00010

и можем использовать grep для извлечения идентификатора. Чтобы проверить, является ли активное окно искомым окном, нам нужно знать, что делает его уникальным, это может быть другим для всех, но, скорее всего, первым фильтром будет свойство WM_CLASS, см. Spec . Вот небольшой пример этого:

#!/bin/bash
class_name=$1

# regex for extracting hex id's
grep_id='0[xX][a-zA-Z0-9]\{7\}'

xprop -spy -root _NET_ACTIVE_WINDOW | grep --line-buffered -o $grep_id |
while read -r id; do
    class="`xprop -id $id WM_CLASS | grep $class_name`"
    if [ -n "$class" ]; then
        # Found a window with the correct WM_CLASS now what makes your
        # window unique?
    fi
done

Использование xprop: Вот суть вопроса в вопросе, где дерево было определяющим фактором. [!d11 ]

Ограничения xprop -spy: это специально не вызывает открытие окна, а не при фокусировке окна. Это означает, что если окно остается открытым, выходит из фокуса, а затем снова фокусируется, этот скрипт будет сообщать об этом событии.

Программирование Xlib: это более сложный, но более мощный. Некоторые полезные ресурсы для начала:

Учебное пособие Xlib и краткое руководство учебника Кристофа Тронче Алана о Xlib.

Для этого нужно открыть соединение и зарегистрироваться в качестве слушателя на X-сервере:

// Open connection to X server
Display *dsp = XOpenDisplay(NIL);
assert(dsp);

// Start listening to root window
XSelectInput(dsp, DefaultRootWindow(dsp), SubstructureNotifyMask);

В зависимости от того, какие события вы ищете Здесь [ ! d13].

Для непрерывного приложения (которое хочет обрабатывать последующие события), вероятно, необходимо установить функцию обработчика ошибок, которая должна возвращать 0 (возможно, с предупреждением), поэтому выполнение продолжается плавно, например:

XSetErrorHandler(bad_window_handler);

В цикле можно обрабатывать события с X-сервера

XEvent e;
XNextEvent(dsp, &e); // blocks until next event from X-server

. Чтобы обработать событие в e, мы можем проверить тип e

e.type == CreateNotify    // A window was created
e.type == ReparentNotify  // A window got a new parent
e.type == MapNotify       // A window was drawn
e.type == DestroyNotify   // A window was destroyed

Структура XEvent содержит информацию в разных типах структуры в зависимости от типа события.

Необходимы следующие библиотеки:

И приложения должны быть скомпилированы с флагом -lX11 для включения библиотек Xlib.

Программирование Xlib: Я создал два gists, которые прослушивают события из X -server. Обратите внимание, что меня интересовала структура дерева окна для идентификации. Другие могут иметь другие свойства для уникальной идентификации окон.

Ограничения xprop -spy прослушивают событие CreateNotify, чтобы определить, создано ли окно с правильным WM_CLASS, вызовите его W. В этот момент окно, вероятно, не будет в правильной древовидной структуре. Например, он может быть создан как дочерний элемент для корня, а не для окон, управляемых приложением. Поэтому мы слушаем событие ReparentNotify, чтобы увидеть, имеет ли W нового родителя.

К сожалению, нам также не гарантируется правильная древовидная структура, так как позже к W можно добавить другие окна. Но если структура дерева W уникальна, и она не является поддеревом другого окна с тем же классом, мы можем, по крайней мере, найти это окно, проверив ReparentNotify (нам, возможно, даже не нужно будет проверять CreateNotify, как мы можем проверьте WM_CLASS в любой точке, у нас есть идентификатор окна).

Второй прослушивает событие MapNotify и проверяет структуру дерева окна. Затем он ищет правильный WM_CLASS в дереве. После этого можно было бы определить правильность структуры.

Опять же, в MapNotify нам не гарантируется «законченная» древовидная структура. Однако кажется, что структура обычно «оседает» через короткое время после этого события. Чтобы быть уверенным, что структура не изменится, я добавил короткую паузу, прежде чем собирать дерево. Как долго эта пауза должна быть для того, чтобы не рисковать другими изменениями в дереве, о котором я не знаю, 500 мс, казалось, работали хорошо для меня.

Разное: окна X11 могут быть созданы в struct [ ! d31], поэтому я предполагаю, что слушать их можно было бы и на многих разных языках.

Некоторые инструменты для изучения окон с помощью:

Руководство Xlib и краткое руководство by Christophe Tronche xwininfo специально с опциями -tree или -children

Также можно проверить исходный код команд выше, xprop и xwininfo, для некоторых рекомендаций и вдохновения. [ ! d51]

3
задан 13 March 2018 в 15:55

12 ответов

Кажется ужасно хакерским, но, похоже, что обновление $PATH работает. Однако я смотрю на побочные эффекты. , ,

Пример:

ExecStart=/bin/bash -c "PATH=/home/someUser/bin:$PATH exec /usr/bin/php /some/path/to/a/script.php"
1
ответ дан 22 May 2018 в 12:36

Кажется ужасно хакерским, но, похоже, что обновление $PATH работает. Однако я смотрю на побочные эффекты. , ,

Пример:

ExecStart=/bin/bash -c "PATH=/home/someUser/bin:$PATH exec /usr/bin/php /some/path/to/a/script.php"
1
ответ дан 17 July 2018 в 18:57

Кажется ужасно хакерским, но, похоже, что обновление $PATH работает. Однако я смотрю на побочные эффекты. , ,

Пример:

ExecStart=/bin/bash -c "PATH=/home/someUser/bin:$PATH exec /usr/bin/php /some/path/to/a/script.php"
1
ответ дан 14 August 2018 в 12:44

Вы можете жестко указать PATH в службе systemd:

[Service]
Environment=PATH=/home/someUser/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

Более гибким будет PAM.

Создайте новую конфигурацию PAM в /etc/pam.d (скажем /etc/pam.d/foo) и добавьте:

session    required     pam_env.so user_envfile=some-file user_readenv=1
bash -c '....', но вы можете сделать это с помощью PAM. ]

И в /home/someUser/some-file добавьте:

PATH DEFAULT=/home/someUser/bin:${PATH}

Конечно, вы можете настроить имя some-file на нечто более разумное, но путь в user_envfile должен быть относительно домашний каталог пользователя (пользователь, который вы установили в User= в службе).

Затем в служебном файле в секции [Service] добавьте (foo в файл в /etc/pam.d ], созданный ранее):

PAMName=foo

Теперь, когда вы запустите службу (после перезагрузки и т. д.), будут запущены модули session в /etc/pam.d/foo, которые в этом случае будут просто [ f18]. pam_env загрузит переменные среды из /etc/environment с ограничениями в /etc/security/pam_env.conf, а затем пользовательскую среду из ~/some-file. Поскольку PATH установлено в значение по умолчанию в /etc/environment, пользовательская среда добавляет к этому значению по умолчанию.

Здесь значением по умолчанию user_envfile является .pam_environment, которое также считывается конфигурацию PAM для других вещей, таких как SSH или LightDM, и т. д. Здесь я использовал другой файл, если вы не хотите влиять на эти вещи. Вы можете удалить user_envfile=... и использовать значение по умолчанию ~/.pam_environment. вы также можете просто использовать существующую конфигурацию PAM в /etc/pam.d, которая имеет user_readenv=1, но другие модули PAM могут вызывать нежелательные побочные эффекты.

2
ответ дан 22 May 2018 в 12:36
  • 1
    Я очень ценю подход pam, поскольку это не произошло со мной. Это, к сожалению, создает огромную сложность для чего-то довольно тривиального. Ваша переменная PATH фактически такая же, как моя, и если я не услышу что-то другое, как я пойду. – Mark 14 March 2018 в 00:55
  • 2
    @Mark Я согласен, я бы использовал его только в том случае, если для моей цели был создан существующий файл конфигурации PAM и файл окружения или мне действительно нужна была немного более высокая гибкость pam_env (вы не можете сделать что-то вроде bar=x foo=${bar} в systemd, но это возможно в pam_env ) – muru 14 March 2018 в 02:28

Кажется ужасно хакерским, но, похоже, что обновление $PATH работает. Однако я смотрю на побочные эффекты. , ,

Пример:

ExecStart=/bin/bash -c "PATH=/home/someUser/bin:$PATH exec /usr/bin/php /some/path/to/a/script.php"
2
ответ дан 23 July 2018 в 19:44
  • 1
    Я очень ценю подход pam, поскольку это не произошло со мной. Это, к сожалению, создает огромную сложность для чего-то довольно тривиального. Ваша переменная PATH фактически такая же, как моя, и если я не услышу что-то другое, как я пойду. – Mark 14 March 2018 в 00:55
  • 2
    @Mark Я согласен, я бы использовал его только в том случае, если для моей цели был создан существующий файл конфигурации PAM и файл окружения или мне действительно нужна была немного более высокая гибкость pam_env (вы не можете сделать что-то вроде bar=x foo=${bar} в systemd, но это возможно в pam_env ) – muru 14 March 2018 в 02:28

Кажется ужасно хакерским, но, похоже, что обновление $PATH работает. Однако я смотрю на побочные эффекты. , ,

Пример:

ExecStart=/bin/bash -c "PATH=/home/someUser/bin:$PATH exec /usr/bin/php /some/path/to/a/script.php"
2
ответ дан 31 July 2018 в 19:00

Кажется ужасно хакерским, но, похоже, что обновление $PATH работает. Однако я смотрю на побочные эффекты. , ,

Пример:

ExecStart=/bin/bash -c "PATH=/home/someUser/bin:$PATH exec /usr/bin/php /some/path/to/a/script.php"
2
ответ дан 2 August 2018 в 12:00

Кажется ужасно хакерским, но, похоже, что обновление $PATH работает. Однако я смотрю на побочные эффекты. , ,

Пример:

ExecStart=/bin/bash -c "PATH=/home/someUser/bin:$PATH exec /usr/bin/php /some/path/to/a/script.php"
2
ответ дан 3 August 2018 в 16:27

Кажется ужасно хакерским, но, похоже, что обновление $PATH работает. Однако я смотрю на побочные эффекты. , ,

Пример:

ExecStart=/bin/bash -c "PATH=/home/someUser/bin:$PATH exec /usr/bin/php /some/path/to/a/script.php"
2
ответ дан 5 August 2018 в 01:50

Кажется ужасно хакерским, но, похоже, что обновление $PATH работает. Однако я смотрю на побочные эффекты. , ,

Пример:

ExecStart=/bin/bash -c "PATH=/home/someUser/bin:$PATH exec /usr/bin/php /some/path/to/a/script.php"
2
ответ дан 6 August 2018 в 18:25

Кажется ужасно хакерским, но, похоже, что обновление $PATH работает. Однако я смотрю на побочные эффекты. , ,

Пример:

ExecStart=/bin/bash -c "PATH=/home/someUser/bin:$PATH exec /usr/bin/php /some/path/to/a/script.php"
2
ответ дан 8 August 2018 в 22:45

Вы можете сделать hardcode PATH в службе systemd:

[Service]
Environment=PATH=/home/someUser/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

Более гибкой будет PAM.

Создайте новую конфигурацию PAM в /etc/pam.d (скажем /etc/pam.d/foo) и добавьте:

session    required     pam_env.so user_envfile=some-file user_readenv=1
bash -c '....', но вы можете сделать это с помощью PAM.

]

И в /home/someUser/some-file добавьте:

PATH DEFAULT=/home/someUser/bin:${PATH}

Конечно, вы можете настроить имя some-file на нечто более разумное, но путь в user_envfile должен быть относительно домашний каталог пользователя (пользователь, который вы установили в User= в службе).

Затем в служебном файле в секции [Service] добавьте (foo в файл в /etc/pam.d ], созданный ранее):

PAMName=foo

Теперь, когда вы запустите службу (после перезагрузки и т. д.), будут запущены модули session в /etc/pam.d/foo, которые в этом случае будут просто pam_env . pam_env загрузит переменные среды из /etc/environment с ограничениями в /etc/security/pam_env.conf, а затем пользовательскую среду из ~/some-file. Поскольку в PATH установлено значение по умолчанию в /etc/environment, среда пользователя добавляет это значение по умолчанию.

Здесь значением по умолчанию user_envfile является .pam_environment, которое также считывается конфигурацию PAM для других вещей, таких как SSH или LightDM, и т. д. Здесь я использовал другой файл, если вы не хотите влиять на эти вещи. Вы можете удалить user_envfile=... и использовать значение по умолчанию ~/.pam_environment. вы также можете просто использовать существующую конфигурацию PAM в /etc/pam.d, которая имеет user_readenv=1, но другие модули PAM могут вызывать нежелательные побочные эффекты.

2
ответ дан 12 August 2018 в 12:10
  • 1
    Я очень ценю подход pam, поскольку это не произошло со мной. Это, к сожалению, создает огромную сложность для чего-то довольно тривиального. Ваша переменная PATH фактически такая же, как моя, и если я не услышу что-то другое, как я пойду. – Mark 14 March 2018 в 00:55
  • 2
    @Mark Я согласен, я бы использовал его только в том случае, если для моей цели был создан существующий файл конфигурации PAM и файл окружения или мне действительно нужна была немного более высокая гибкость pam_env (вы не можете сделать что-то вроде bar=x foo=${bar} в systemd, но это возможно в pam_env ) – muru 14 March 2018 в 02:28

Другие вопросы по тегам:

Похожие вопросы: