systemctl은 실행 파일을 찾을 수 없지만 루트는 찾을 수 있습니까?

systemctl은 실행 파일을 찾을 수 없지만 루트는 찾을 수 있습니까?

이상한 점: 저는 springboot fat archive 웹서버를 시작하는 서비스를 만들었습니다. 제공하다:

#!/bin/bash
[Unit]
Description=JalouWeb

[Service]
Type=simple
WorkingDirectory=/opt/jaloucontrol
ExecStart=/bin/bash jalouweb.sh

TimeoutStartSec=0
RestartSec=60
Restart=always
SyslogIdentifier=jalouweb

[Install]
WantedBy=multi-user.target

jalouweb.sh:

#! /bin/sh
#
java -Duser.timezone=Europe/Berlin -Dfile.encoding=UTF-8 -jar jcweb-0.0.1-SNAPSHOT.jar

jalouweb.sh를 사용자로 시작하면 됩니다. sudo -i를 실행하고 jalouweb.sh를 루트로 시작합니다. 사용자와 루트 모두 성공적으로 java -version을 호출할 수 있습니다.

하지만 systemctl을 통해 서비스를 시작하면 다음과 같은 메시지가 나타납니다.

... jalouweb.sh: Zeile 3: java: Kommando nicht gefunden.(<- command not found)
...  systemd[1]: jalouweb.service: Main process exited, code=exited, status=127/n/a

jalouweb.sh에 경로를 추가하면 다음과 같습니다.

/opt/openjdk17/bin/java -Duser.timezone=Europe/Berlin...

systemctl도 성공했습니다. 그런데 왜? Afaik 사용자 없이 서비스를 실행한다는 것은 루트로 실행한다는 의미입니다. 루트는 sh와 java를 직접 시작할 수 있습니다. systemctl에 명시적인 경로가 필요한 이유는 무엇입니까?


편집: 나는 wenshuo의 제안을 따랐습니다. 서비스가 성공적으로 실행되지만 tmplog 파일은 생성되지 않지만 Journalctl은 다음을 보여줍니다.

systemd[1]: Started JalouWeb. 
jalouweb[11189]:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin > /tmp/tmplog  
systemd[1]: jalouweb.service: Succeeded.

echo 명령이 실제로 올바르지 않은 것 같습니다. 그러나 핵심 정보는 다음과 같습니다. 비대화형 루트 경로에 java가 없습니다.


편집 2 @Stephane: 스크립트를 찾거나 실행하는 데 문제가 없습니다. 문제는 스크립트에서 호출된 Java를 찾을 수 없다는 것입니다. systemctl의 실행자에게 경로나 JAVA_HOME을 제공하는 방법을 알아내야 합니다.

답변1

bash some-path

어디some-path/다음과 같은 문자가 포함되어 있지 않습니다 .아니요사용. 상황이 더 나쁠지라도 이는 여러 다른 Korn 유사 쉘1 및 .내장2 source또는 많은 Bourne 유사 쉘 에 적용됩니다 bash.

bash이는 프로그래밍 언어의 인터프리터와 마찬가지로 Bash 프로그래밍 perl언어의 인터프리터 입니다 Perl.

bash /path/to/some/Bash/file표준 입력의 코드가 아닌 주어진 파일의 Bash/Perl 코드를 perl /path/to/some/Perl/file말하거나 해석하는 방법 bash과 같습니다 .perl

예를 들어 다음과 같은 용도로 사용됩니다.

#! /bin/bash -

실행 후 시스템은 이를 파일의 내용 으로 변환 /bin/bash - path/to/the/file하고 해석합니다.bash

그리고 실행 중이지만 실행되지는 않습니다./bin/bash some-pathsystemdbashbash구현하다 some-path3, 단지 그것을 읽고 그 안의 Bash 코드를 해석합니다.

지금, 언제some-path/동작 변경 사항이 포함되어 있지 않습니다 bash. bash먼저 일반 경로로 해석되므로 여기서는 현재 작업 디렉터리에 상대적이지만 파일을 찾을 수 없는 경우 $PATH일부 기본 검색 목록의 환경 변수(또는 설정되지 않은 경우)의 디렉터리 구성 요소에서 해당 파일을 찾습니다. ).

이 행동은허용하다POSIX에서는 필요하지 않지만 POSIX에서는실행 가능 파일그 과정에서 발견된 파일. Bash(최소 버전 5.2)는 POSIX 모드에서도 실행 불가능한 파일을 찾아 비규격으로 만들 수 있습니다.

bash여기에서는 스크립트가 있는 디렉터리에서 스크립트를 해석해야 하며 다음을 수행해야 합니다.

WorkingDirectory=/path/to/that/dir
ExecStart=/bin/bash ./the-script

( ./경로에 접두사 a가 포함되어 있는지 확인하고 /어떤 $PATH이유로 현재 작업 디렉토리가 누락된 경우 조회를 비활성화하십시오.)the-script

WorkingDirectory지정하지 않으면 기본값은 시스템 /서비스와 사용자의 홈 디렉터리입니다.

또는 스크립트의 전체 경로를 지정해야 합니다.

ExecStart=/bin/bash /path/to/that/dir/the-script

실행 파일을 들여쓰기 the-script하고 해석하여 find 로 bash찾은 경우 실행 권한( )이 있는 shebang이 있고 에 저장되어 있는지 $PATH확인하세요 .#! /bin/bash -chmod a+x$PATHsystemd

그리고 다음을 사용하세요:

ExecStart=the-script

파일이 실행 가능하다면 확장자를 제거하는 것이 좋습니다 .sh. 그렇지 않고 Bash 언어로 작성된 경우 .bash대신 확장을 사용하는 것이 좋습니다. .sh표준 구문이 아닌 경우 sh오해의 소지가 있습니다 .


¹ 이것은 sh 또는 ksh 에뮬레이션에서 zsh의 경우이며, ksh가 이 버그 기능의 소스일 수 있습니다.

² .이것은 실제로 특수 내장 기능의 경우 POSIX보다 더 나쁩니다.필요 /- 적은 경로가 검색됩니다 $PATH(그리고 현재 작업 디렉터리로 대체됩니다). 일부 셸에서는 요구 사항이 무시됩니다(POSIX 모드가 아닌 경우 bash 포함).

³ 여기에 있는 bash -c the-script텍스트는 the-scriptbash에 의해 인라인 셸 코드로 해석되어 간단한 명령으로 해석되므로 차이가 있습니다 $PATH.실행 가능 파일이를 수행하는 명령(스크립트 또는 비스크립트)구현하다.

답변2

실행 파일을 찾기 위해 쉘은 $PATH변수에 나열된 디렉토리를 검색합니다. $PATH디렉터리의 경로 이름을 포함하면 실행 파일의 전체 경로 이름을 제공하지 않고도 해당 디렉터리에서 실행 파일을 호출할 수 있습니다 .

echo "$PATH"셸에서 현재 경로 목록을 볼 수 있습니다 . 귀하의 경우에는 대화형 쉘에 사용하는 것과 다를 수 $PATH있습니다 .systemctlroot

$PATH다음 명령을 사용하여 에서 사용된 값을 볼 수 있습니다.systemctl

ExecStart=/bin/echo "$PATH" > /tmp/tmplog

... [Service]유닛 파일의 섹션에 있습니다. $PATH그러면 의 값이 에 기록 됩니다 /tmp/tmplog.

관련 정보