Bash 스크립트는 Centos 7에서 완벽하게 실행되지만 Ubuntu Bionic에서는 실패합니다.

Bash 스크립트는 Centos 7에서 완벽하게 실행되지만 Ubuntu Bionic에서는 실패합니다.

아래 스크립트를 찾아주세요

if [ "$#" -eq 0 ]; then
  dbs=('test_db_1' 'test_db_2') 
  path='/var/backups/'
else
  dbs=( "$@" )
  path='/app/mybackups/'
fi
dbuser='test_user_name'
dbpassword='test_pass_word'
now="$(date +'%d-%m-%Y_%T')"
currentDate="$(date)"
dayToSubtract=365
cd ${path}
echo "location: $path"
for element in ${dbs[@]}
        do
                echo $element
                echo "Starting backup now for db: $element on $now"
                mongodump -u ${dbuser} -p ${dbpassword} --authenticationDatabase 'admin' -d $element --gzip --archive=${element}_$now.archive
                dateToBeRemoved=$(date --date="${currentDate} -${dayToSubtract} day" +%d-%m-%Y)
                echo $dateToBeRemoved
                fileToBeRemoved="${element}_${dateToBeRemoved}"
                echo Removing $fileToBeRemoved
                rm $fileToBeRemoved*
        done
echo All Done!
echo "location: $path"

저는 이 스크립트를 1년 넘게 매일 서버의 데이터베이스를 백업하는 데 사용해 왔으며 스크립트에 명령줄 인수를 전달하여 수동 백업을 수행하는 데에도 사용했습니다.

최근에 우분투를 사용하는 새 서버를 얻었는데 다음 오류가 발생했습니다.

daily.sh: 2: daily.sh: Syntax error: "(" unexpected (expecting "fi")

참고로 아래 스크린샷을 참조하세요.

여기에 이미지 설명을 입력하세요.

추가한 후:

#!/usr/bin/env bash

여기에 이미지 설명을 입력하세요.

같은 오류가 발생했습니다.

여기에 이미지 설명을 입력하세요.

어떤 bash를 실행하면 다음을 얻습니다.

여기에 이미지 설명을 입력하세요.

bash 결과를 기반으로 shebang을 추가했지만 여전히 동일한 문제가 발생합니다. 여기에 이미지 설명을 입력하세요.

현재 폴더에서 실행하는 경우:

여기에 이미지 설명을 입력하세요.

BOM 확인:

여기에 이미지 설명을 입력하세요.

우분투 정보: 게시자 ID: Ubuntu 설명: Ubuntu 18.04.3 LTS 버전: 18.04 코드명: bionic

답변1

스크립트의 첫 번째 줄에 shebang을 추가하세요: (
댓글에서)

#!/usr/bin/env bash 

아니면 길을 알고 계시다면.

#!/bin/bash

또는

#!/usr/bin/bash

그것이 어디에 있든 상관 없습니다.

답변2

컨텍스트와 세부 정보를 추가하므로 이전 답변을 아래에 남겨 두겠습니다. 그런데 당신의 오해는 sh yourscript당신이 무엇을 해야 한다고 생각하는 데서 비롯된 것 같아요 .

그것이 하는 일은 사용입니다 sh(알다시피 이것은 시스템마다 다릅니다...).역자전달한 스크립트 이름에 대해.

너 뭐야~인 것 같다그러나 계획은

sh -c "your command ... whatever it is"

sh이제 왜 다음과 같이 사용한다고 주장합니까?역자귀하의 의견과 두 가지 답변에서 이것이 틀렸다는 말을 들었을 때 나는 모르겠습니다.

스크립트가 실행 가능하고 올바른 해시뱅을 가지며 PATH상대 또는 절대 경로를 사용하여 찾거나 호출되는 경우작동할 것이다.

sh하지만 통역사 사용을 고집한다면 기본적으로적극적으로당신을 도우려는 모든 시도 sh는 다르다는 이유로 방해하세요 sh -c COMMAND. 귀하의 통역사가 Bash가 아닌 경우 Bashism 사용이 실패할 수 있습니다(당신이 목격한 것처럼).

이 실패를 "더 안정적"으로 만들고 싶다면 #!/bin/sh제안된 대로 대신 hashbang을 사용하여 이를 확실하게 설정할 수 있습니다. 이렇게 하면 sh명령줄에서 스크립트를 전달하는 것과 동일한 결과가 생성됩니다.


여기에 몇 가지 질문이 있습니다. 스크린샷에는 스크립트가 실행 가능하지 않음( root:root파일 모드 0644 소유)이 표시됩니다. 따라서 이를 사용하여 실행하려고 하면 시스템에 있는 모든 쉘을 sh사용하게 됩니다 .sh

실패 이유는 세 가지입니다.

  • 귀하의 스크립트는 실행 가능하지 않으며 다음 위치에 없습니다.PATH
  • sh yourscript실행 가능하지 않기 때문에 인터프리터 역할을 하도록 만드십시오 sh(우분투의 경우 dash모든 Bashism을 이해하지는 못하지만).
  • 귀하의 스크립트에 "바이너리"에 사용할 통역사에 대한 단서를 로더에 제공하는 해시뱅이 없습니다.

그러나 다음과 같은 해시뱅을 추가하면:

#!/usr/bin/env bash 

...스크립트에 다음이 포함되어 있지 않은지 확인한 경우자재 명세서실행 가능하다고 확신하는 경우:

chmod +x daily_ori.sh

...그리고 상대 경로를 사용합니다(또는 현재 경로를 에 추가 PATH하지만 이는 좋지 않습니다!).

sh ./daily_ori.sh

... 이것~해야 한다성공. 귀하의 질문에 더 많은 정보가 누락되지 않은 한.

그러나 마지막 단계는 의문을 제기합니다. shBash를 호출하는 것이 목적이라면 애초에 스크립트 실행을 고집하는 이유는 무엇입니까? 해시뱅(하드코딩되었거나 사용된 env)을 사용하여 인터프리터를 찾고 bash, 스크립트가 실행 가능한지 확인한 후 평소처럼 호출하세요.


BOM을 확인하려면 다음을 사용하세요.

xxd -g 1 daily_ori.sh|head -n 2

...질문에 맞게 편집하세요.

관련 정보