실험 1

실험 1

3개의 다른 폴더를 모니터링하고 그 중 하나가 변경되면 스크립트를 실행해 보세요. 문제는 스크립트가 어떤 폴더가 변경되었는지 알아야 하는데 이를 전달할 방법을 찾을 수 없다는 것입니다.

[Path]
PathChanged=/x/y/z
PathChanged=/a/b/c
PathChanged=/foo/bar
Unit=123.service

[Install]
WantedBy=multi-user.target

나는 이것을 할 방법이 없다고 가정하고 있습니다. 그리고 3개의 별도 .path 파일이 있거나(으악) 폴더 중 하나가 변경될 때마다(비효율적이고 총체적) 스크립트가 3개 폴더 모두에 대해 반복되도록 해야 합니다.

그런데 여기에 물어봐야겠다고 생각했어요. 어쩌면 시스템 변수가 누락되었거나 시스템이 없는 더 효율적인 변수가 누락되었을 수도 있습니다. 그래서 거기에 있나요?

감사해요.

답변1

*.path몇 가지 실험을 거친 후 가장 쉬운 방법은 경로당 하나의 파일을 사용 하고 각 경로를 *@.service파일로 템플릿화하는 것임을 알았습니다. 귀하의 예를 사용하면 다음과 같습니다.

$ systemctl --user cat 123* *.path
# /home/stew/.config/systemd/user/[email protected]
[Service]
Type=oneshot
ExecStart=/bin/echo %I

# /home/stew/.config/systemd/user/abc.path
[Path]
PathChanged=/a/b/c
[email protected]

# /home/stew/.config/systemd/user/foobar.path
[Path]
PathChanged=/foo/bar
[email protected]

# /home/stew/.config/systemd/user/xyz.path
[Path]
PathChanged=/x/y/z
[email protected]

*.service경로는 다음을 통해 액세스 할 수 있습니다 .%I 지정자

Unit=내가 사용한 이름을 얻으려면시스템 탈출:

$ systemd-escape [email protected] \
      '/x/y/z' \
      '/a/b/c' \
      '/foo/bar'
[email protected] [email protected] [email protected]

관련 매뉴얼 페이지:

더 쉬운 해결책이 있는지 궁금하다면 제가 시도한 방법은 다음과 같습니다.


실험 1

가정: 환경 변수에 있습니다.

시스템 실행(5)환경 변수 목록을 제공합니다. $RUNTIME_DIRECTORY또는 같은 것을 설정할 수 있습니다 .$LISTEN_FDS

실험 설정:

$ mkdir /home/stew/systemdpath
$ systemctl --user cat simplepath.*
# /home/stew/.config/systemd/user/simplepath.path
[Unit]
Description=Path testing

[Path]
DirectoryNotEmpty=/home/stew/systemdpath

# /home/stew/.config/systemd/user/simplepath.service
[Unit]
Description=Path testing unit

[Service]
Type=oneshot
ExecStart=/usr/bin/env
$ systemctl --user start simplepath.path

실험 결과:

$ touch ~/systemdpath/file
$ journalctl --user simplepath.service
Jul 28 08:26:16 stewbian systemd[31634]: Starting Path testing unit...
Jul 28 08:26:16 stewbian env[334512]: HOME=/home/stew
Jul 28 08:26:16 stewbian env[334512]: LANG=en_GB.UTF-8
Jul 28 08:26:16 stewbian env[334512]: LANGUAGE=en_GB:en
Jul 28 08:26:16 stewbian env[334512]: LOGNAME=stew
Jul 28 08:26:16 stewbian env[334512]: PATH=/home/stew/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
Jul 28 08:26:16 stewbian env[334512]: SHELL=/bin/bash
Jul 28 08:26:16 stewbian env[334512]: USER=stew
Jul 28 08:26:16 stewbian env[334512]: XDG_RUNTIME_DIR=/run/user/1000
Jul 28 08:26:16 stewbian env[334512]: GTK_MODULES=gail:atk-bridge
Jul 28 08:26:16 stewbian env[334512]: QT_ACCESSIBILITY=1
Jul 28 08:26:16 stewbian env[334512]: DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus
Jul 28 08:26:16 stewbian env[334512]: DESKTOP_SESSION=/usr/share/xsessions/i3
Jul 28 08:26:16 stewbian env[334512]: DISPLAY=:0
Jul 28 08:26:16 stewbian env[334512]: GPG_AGENT_INFO=/run/user/1000/gnupg/S.gpg-agent:0:1
Jul 28 08:26:16 stewbian env[334512]: PAM_KWALLET5_LOGIN=/run/user/1000/kwallet5.socket
Jul 28 08:26:16 stewbian env[334512]: PWD=/home/stew
Jul 28 08:26:16 stewbian env[334512]: SHLVL=1
Jul 28 08:26:16 stewbian env[334512]: XAUTHORITY=/home/stew/.Xauthority
Jul 28 08:26:16 stewbian env[334512]: XDG_CURRENT_DESKTOP=i3
Jul 28 08:26:16 stewbian env[334512]: XDG_SEAT_PATH=/org/freedesktop/DisplayManager/Seat0
Jul 28 08:26:16 stewbian env[334512]: XDG_SESSION_CLASS=user
Jul 28 08:26:16 stewbian env[334512]: XDG_SESSION_DESKTOP=i3
Jul 28 08:26:16 stewbian env[334512]: XDG_SESSION_PATH=/org/freedesktop/DisplayManager/Session5
Jul 28 08:26:16 stewbian env[334512]: XDG_SESSION_TYPE=x11
Jul 28 08:26:16 stewbian env[334512]: _=/usr/bin/dbus-update-activation-environment
Jul 28 08:26:16 stewbian env[334512]: MANAGERPID=31634
Jul 28 08:26:16 stewbian env[334512]: INVOCATION_ID=837f6b2e56b543c9b51cda4ee8952fa8
Jul 28 08:26:16 stewbian env[334512]: JOURNAL_STREAM=8:21581980
Jul 28 08:26:16 stewbian systemd[31634]: simplepath.service: Succeeded.
Jul 28 08:26:16 stewbian systemd[31634]: Finished Path testing unit

결론적으로:

Systemd는 경로를 환경 변수에 넣지 않습니다.


실험 2

가정: 템플릿화 가능

$LISTEN_FDS소켓과 경로 사이에는 몇 가지 유사점이 있다는 점을 고려하십시오 . 소켓은 다음과 같은 경우에 템플릿화됩니다.Accept=yes설정되어 있으므로 경로를 사용하려고 하면 어떻게 되나요?

기본 설정:

$ systemctl --user cat simplepath*
# /home/stew/.config/systemd/user/simplepath.path
[Unit]
Description=Path testing

[Path]
DirectoryNotEmpty=/home/stew/systemdpath
[email protected]

# /home/stew/.config/systemd/user/[email protected]
[Unit]
Description=Path testing unit

[Service]
Type=oneshot
ExecStart=/bin/echo %i

실험 결과:

$ systemctl --user start simplepath.path
$ touch ~/systemdpath/file
$ journalctl --user --since "5 minutes ago"
Jul 28 09:14:25 stewbian systemd[31634]: Starting Path testing unit...
Jul 28 09:14:25 stewbian echo[336171]: simplepath
Jul 28 09:14:25 stewbian systemd[31634]: [email protected]: Succeeded.

결론적으로

서비스에 에코된 인스턴스는 서비스 이름 자체입니다. 그것은 도움이 되지 않습니다.


실험 3

가정: 각 경로에는 자체 파일과 서비스 템플릿이 있을 수 있습니다.

실험 설정:

$ mkdir ~/path1
$ mkdir ~/path2
$ systemctl --user cat path*
# /home/stew/.config/systemd/user/path1.path
[Unit]
Description=Path1 testing

[Path]
DirectoryNotEmpty=%h/path1
[email protected]

# /home/stew/.config/systemd/user/path2.path
[Unit]
Description=Path2 testing

[Path]
DirectoryNotEmpty=%h/path2
[email protected]

# /home/stew/.config/systemd/user/[email protected]
[Unit]
Description=Path testing unit

[Service]
Type=oneshot
ExecStart=/bin/echo %h/%i
$ systemctl --user start path1.path path2.path

실험:

$ touch ~/path1
$ touch ~/path2
$ journalctl --user --since "5 minutes ago"
Jul 28 09:43:45 stewbian systemd[31634]: Starting Path testing unit...
Jul 28 09:43:45 stewbian echo[336517]: /home/stew/path1
Jul 28 09:43:45 stewbian systemd[31634]: [email protected]: Succeeded.
Jul 28 09:43:45 stewbian systemd[31634]: Finished Path testing unit.
Jul 28 09:43:50 stewbian systemd[31634]: Starting Path testing unit...
Jul 28 09:43:50 stewbian echo[336519]: /home/stew/path2
Jul 28 09:43:50 stewbian systemd[31634]: [email protected]: Succeeded.
Jul 28 09:43:50 stewbian systemd[31634]: Finished Path testing unit.

결론적으로

템플릿 기반 서비스 단위를 여러 경로 단위에 적용할 수 있습니다. 이 방법이 가장 쉬운 방법인 것 같습니다.

여기서 문제는 서비스가 %h홈 디렉토리를 사용한다는 것입니다. /템플릿 이름에 해당 문자를 포함 하면 문제가 발생합니다.시스템 탈출(1)이 문제를 해결하는 데 도움이되는 것 같습니다.

답변2

systemd(예: RedHat 6.x)가 도입되기 전의 일부 Linux에서는 systemd.path 솔루션보다 더 간단하고 완전한 incrontab 명령을 설치하고 사용할 수 있습니다. Incrontab과 incrond는 inotify API에 대한 강력한 인터페이스를 제공하지만 불행하게도 incrontab에 비해 불완전한 systemd.path로 대체됩니다. incrontab은 systemd를 사용하여 현재 버전에 계속 설치할 수 있지만 현재 유지 관리되지 않으므로 프로덕션 또는 중요한 시스템에는 적합하지 않습니다. 이 문제가 향후 버전에서 수정되기를 바랍니다.

관련 정보