Bash 스크립트 - 종료하는 대신 오류가 발생하면 반환됩니까?

Bash 스크립트 - 종료하는 대신 오류가 발생하면 반환됩니까?

그래요터미널에서 bash 스크립트 가져오기, 따라서 오류 종료

set -o errexit

터미널을 닫고 다른 터미널을 연 다음 일부 변수를 재설정해야 하기 때문에 매우 짜증나는 터미널이 종료됩니다.

지금까지 사용하여

command || return

스크립트의 줄이 내가 원하는 대로 작동하고 있습니다.

set -o errexit

해야 할 일...하지만 한 줄/명령만이 아닌 전체 스크립트가 완료되기를 원합니다.

사이트 설정을 위한 명령으로 가득 찬 파일이 있지만 명령을 실행하고 싶지 않습니다.

파일의 각 줄에 대해

다른 설정 옵션이 있거나 터미널을 종료하는 대신 "반환"하는 다른 옵션이 있습니까?

--단지 명확성을 위해, 스크립트를 종료하고 터미널에서 실행 중인 서비스를 종료하기 위해 Ctrl+C를 누른 것과 동일한 상태로 터미널을 두고 싶습니다. command || return이 방법. 하지만 || return파일의 모든 줄에 추가하고 싶지는 않습니다 . 그래서 저는 set -o errexit터미널이 닫히지 않는 이와 같은 것을 찾고 있습니다 .

- - 노트: 두 줄을 포함하는 단순 스크립트(super.sh)를 만듭니다.

create_path=~/Desktop/site_builder/create.sh
source $create_path blah

set -o errexitcreate.sh 상단에 배치됩니다 .

내가 예상한 대로 정확하게 작동합니다. 그러나 터미널에서 호출하는 대신 다른 bash 스크립트를 호출하기 위해 두 줄로 파일을 생성해야 하는 것은 정말 어리석은 일입니다. 어 어 어

여기 몇 가지 예가 있어요.

super.sh에서

#!/bin/bash

create_path=~/Desktop/site_builder/create.sh
source $create_path blah

create.sh에서

#!/bin/bash
set -o errexit
#line below this is a line that fails and will cause the script to stop and return to the terminal as expected 
sed "s/@@SITE_NAME@@/$dirname" 
~/Desktop/site_builder/template_files/base.html > ~/Desktop/$dirname/templates/base.html # a line with a stupid error

터미널에서:

 $ bash super.sh

출력은 예상대로입니다.

my-mac$

이것은 작동합니다. 정말 짜증나는 해결책입니다.

생각하다이상적으로는 터미널을 닫지 않고 super.sh 파일이 아닌 터미널에서 멍청한 super.sh 파일의 내용을 실행하세요 :D. 이것이 내가하려는 일에서 일어나는 일입니다.

터미널 명령:

my-mac$ source $create_path blah

create.sh에는 아직set -o errexit

이것은 터미널의 출력입니다.

    sed: 1: "s/@@SITE_NAME@@/blah": unterminated substitute in regular expression
Saving session...
...copying shared history...
...saving history...truncating history files...
...completed.

[Process completed]

그러면 터미널이 정지됩니다. Ctrl+C가 작동하지 않고, Ctrl+D도 작동하지 않습니다.

그렇지 않은 경우 create.sh 파일의 아무 곳에서나 명령문을 사용 set -o errexit하면 command || return(터미널에서 super.sh를 호출하는 대신) 터미널에서 직접 superser.sh의 행을 실행하는 동안 원하는 것을 얻을 수 있습니다. 하지만 이것도 실용적인 해결책은 아니다.

노트:( )서브셸 생성에 대한 @terdon의 답변이 마음에 들었기 때문에 전체 스크립트 주위에 중괄호를 사용하여 답변에서 보여준 것처럼 터미널 대신 스크립트를 통해 서브셸을 생성하게 되었습니다 . 그의 대답도 효과가 있습니다.

답변1

파일을 얻으려면 안전 장치를 사용하십시오.

source the-source-file || true

...그러면 실패하더라도 전체 명령이 실패하지 않습니다 source.

답변2

이것이 내가 달성해야 하는 작업에 작동하는 유일한 방법입니다(가상 환경을 생성한 다음 활성화한 다음 bash 스크립트에서 요구 사항을 설치).

다음과 같은 스크립트에서 하위 쉘/하위 쉘을 생성하십시오.

바보 파일 .sh

(
set -o errexit
#bunch of commands
#one line fails
)

다음을 사용하여 어리석은 파일을 실행하십시오.

source stupid_file.sh <file arguments here> || true

마치다.

**절하다**

(Jeff와 Terdon의 크레딧)

답변3

set -o errexit대신 다음을 사용할 수 있습니다 trap.

trap 'trap - ERR RETURN; kill -INT $$ ; return' ERR RETURN

kill -INT $$동작은 비슷 exit하지만 스크립트가 소스로 제공되면 아무 작업도 수행하지 않습니다(대신 실행됩니다 return)(입력 프롬프트가 신호를 포착하여 쉘이 종료되는 것을 방지하기 때문에 이것이 작동한다고 생각합니다).

trap - ...스크립트가 종료된 후에 실행되지 않도록 트랩을 비활성화합니다.

답변4

간단한 해결 방법으로 현재 셸 내에서 셸을 실행하고 그곳에서 소스 코드를 얻을 수 있습니다. 그것은 다음과 같습니다:

  1. 새 터미널을 열고 원하는 대로 모든 것을 설정하세요. 일부 환경 변수 등을 언급하셨습니다. 여기에서 설정하세요.

  2. 해당 터미널에서 새 쉘을 시작하십시오. 예를 들어, bash.

  3. 당신의 일을 하세요. 스크립트를 받으세요. 종료되면 첫 번째 셸로 이동하고 모든 것이 여전히 설정됩니다. 다시 실행 bash하면 정상으로 돌아옵니다.

이를 설명하기 위해 다음 스크립트를 만들었습니다. 이 스크립트는 얻으려고 하면 실패합니다.

$ cat /home/terdon/scripts/bar.sh
set -o errexit
var='bar

중첩된 쉘 세션을 시작한 다음 이를 가져오면 어떤 일이 발생하는지 살펴보겠습니다(명령의 휴대용 이름을 사용한다는 점에 유의하세요 source. .; source는 bashism입니다).

parent-shell $ bash      ## start a new shell
child-shell $ . ~/scripts/bar.sh
bash: /home/terdon/scripts/bar.sh: line 2: unexpected EOF while looking for matching `''
parent-shell $ 

보시다시피 구문 오류로 인해 소스 스크립트가 종료되고 이로 인해 쉘 세션이 종료되지만 이는 중첩 세션이므로 모든 변수가 여전히 설정된 원래 상위 쉘로 돌아갑니다. 이제 새 셸을 다시 실행하면 돌아가서 스크립트를 가져올 수 있습니다.

관련 정보