이 스크립트에 어떤 문제가 있나요?

이 스크립트에 어떤 문제가 있나요?

그래서 저는 이 가이드에서 이 스크립트를 얻었습니다: www.tldp.org/LDP/abs/abs-guide.pdf

LOG_DIR=/var/log
ROOT_UID=0
LINES=50
E_XCD=86
E_NOTROOT=87

if [ "$UID" != "$ROOT_UID" ]
then
echo "Must be root to run this script."
exit $E_NOTROOT
fi

if [ -n "$1" ]
then
lines=$1
else
lines=$LINES
fi

cd $LOG_DIR

if [ 'pwd' != "$LOG_DIR" ]
then
echo "Can't change to $LOG_DIR."
exit $E_XCD
fi

이제 터미널에서 sudo su를 실행하고 $UID를 에코하여 0을 제공합니다. 즉, 내 if 조건이 거짓으로 판명되었지만 여전히 "이 스크립트를 실행하려면 루트여야 합니다."라는 메시지가 표시됩니다. 이 스크립트를 실행하는 동안.

또한 원본 스크립트에서는 if 조건이 다음과 같이 제공되었습니다.

if [ "$UID" -ne "$ROOT_UID" ]

하지만 -ne은 문자열에만 사용되기 때문에 잘못된 숫자 오류가 발생하여 !=로 변경했습니다.

답변1

그것을 실행하는 대신

sh script.sh

그것을 실행

bash script.sh

(또는 #!/bin/bash인터프리터를 설정하려면 첫 번째 줄에 추가하세요)

우분투의 쉘 sh~ 아니다 bash이지만 dash. dash에는 처럼 많은 기능이 없으므로 bash더 효율적이지만 이러한 누락된 기능으로 인해 에서 의도된 스크립트가 중단되는 경우가 있습니다 bash. 그러한 특징 중 하나는 $UID변수입니다.정의되지 않음안에 dash.

dash, 스크립트가 에서 실행될 때 비교는 가 되며 ["" != "0"], 어떤 사용자가 이를 실행하든 상관없이 true로 평가됩니다. 그러나 루트 권한으로 실행하면 bash문자열이 동일하고 스크립트가 작동합니다.

답변2

처럼맥 로빈 라고, 자동으로 설정된 읽기 전용 UID(및 EUID) 변수는 의 특수 기능입니다.bash(그리고 다른 껍질들). 에 대한 표준이 아닙니다.본 스타일 쉘sh이러한 변수를 설정한다고 가정할 수는 없습니다 . 특히 sh우분투에서는 (현재 기본적으로)dash, 이는 설정되지 않습니다.

두 가지 옵션이 있습니다:

  1. bash대신에 스크립트가 실행되도록 하세요 sh.
  2. 이식성이 뛰어나고 bash.

다음을 사용하여 스크립트 실행bash

스크립트 이름을 알려주지 않았습니다(괜찮습니다). 내가 전화할게cleanup, 이는 작업 중인 가이드에 있는 유사한 스크립트의 이름이기 때문입니다.

특히 저는~ 아니다그것을 다음과 같이 부릅니다 cleanup.sh. 접미사를 사용하여 이름을 지정하는 것을 권장하지 않기 때문입니다 .sh.

  • 접미사 .shsh!
  • 대부분의 스크립트에는 접미사가 전혀 제공되지 않으며 또는 접미사가 있으면 .sh파일 .bash이 "최상위" 스크립트가 아닌 "라이브러리"임을 암시하는 것으로 해석될 수도 있습니다. 즉, .실제로 직접 실행되기보다는 다른 스크립트(예: 내장 스크립트)에서 제공되는 코드를 제공합니다 .

그러나 .sh접미사를 포함해도 스크립트의 기술적인 동작에는 어떤 방식으로도 영향을 미치지 않습니다. 그렇게 하는 것과 관련된 기술적인 이점이나 단점은 없습니다.

을 추가하다해시뱅 라인스크립트의 첫 번째 줄에:#!/bin/bash

스크립트를 실행 가능하게 만드세요와 함께 .chmod +x cleanup

이제 할 수 있습니다스크립트를 실행하세요다음 명령을 실행하여:

  • ./cleanup, 현재 디렉터리에 있는 경우. (특히 교육, 탐색, 테스트, 재미 또는 기타 제한적이거나 일회성 사용을 위해 스크립팅하는 경우 이것이 아마도 가장 일반적인 방법일 것입니다.)

  • /path/to/cleanup, 일반적으로. 명령의 첫 번째 단어에 가 포함되어 있으면 /실행 파일의 경로로 해석됩니다. ( 현재 디렉토리를 의미하는 ./것처럼 위 구문 의 이유입니다 .).

    에 의해첫번째 단어내 말은 첫 번째 명령을 포함하지 않고 최대 명령을 의미합니다.이스케이프되지 않은space 또는 tab:
    foo-bar/baz은 의 첫 번째 단어이고 foo-bar/baz qux, 이전 공백은 백슬래시로 이스케이프되므로 spam\ ham는 의 첫 번째 단어입니다 .spam\ ham eggsham

  • cleanup, 해당 디렉터리에 있는 경우 PATH(먼저 나열된 디렉터리에 동일한 이름의 실행 파일이 없고 다음으로 대체되지 않은 경우)쉘 내장,기능, 또는별명).

스크립트 여부에 관계없이cleanuphashbang 줄이 있거나 #!...그 줄이 말하는 내용이 있습니다.

  • sh cleanupsh여전히 통역사로 실행하려고 시도합니다 .
  • bash cleanupbash여전히 통역사로 실행하려고 시도합니다 .

이러한 경우에는 실제로 인터프리터( sh또는 bash)를 실행하고 실행할 스크립트 이름을 인터프리터에 전달하기 때문입니다. 많은 프로그램은 명령줄에서 열 파일 이름을 허용하며 쉘은 이 규칙을 따릅니다 sh.bash

스크립트를 이식 가능하게 만들기

스크립트를 이식 가능하게 만들고 싶다면 가장 간단한 방법은 $UID전혀 사용하지 않고 대신 모든 Bourne 스타일 쉘에서 사용할 수 있는 일부 기능을 사용하는 것입니다.

일반적으로 사용자 ID를 확인하는 내장 셸 기능은 없습니다. 하지만 당신은 사용할 수 있습니다id. 이것은 쉘 내장이 아닌 외부 프로그램이지만 다음과 같습니다.cat그리고ls, 그것이 존재할 것이라고 기대하는 것이 합리적입니다.

id그 자체로는 많은 정보를 출력하지만 id -u유효한 사용자 ID만 제공합니다.

따라서 대신 다음을 if [ "$UID" != "$ROOT_UID" ]사용할 수 있습니다.

if [ "$(id -u)" != "$ROOT_UID" ]

기술적으로, 이것은 동일하지 않습니다. $UIDin은 bash실제 사용자 ID를 제공하며 id -u실제로 bash는 ' 에 해당합니다 $EUID. EUID가 아닌 UID를 정말로 원한다면 id -ru.

관련 정보