도커 진입 점 스크립트에 대해 set -e 및 exec“$ @”의 기능은 무엇입니까?


90

docker에 대한 많은 entrypoint.sh 스크립트가 다음과 같은 작업을 수행한다는 것을 알았습니다.

#!/bin/bash
set -e

... code ...

exec "$@"

무엇 set -e과은 exec "$@"을 위해?


2
참조 BashFAQ # 105 재 : 왜 set -e오류가 발생하기 쉬운 손으로 쓴 오류 처리보다 훨씬 더 간주됩니다. (급한 경우 아래 연습에 대한 상단의 비유를 건너 뜁니다).
Charles Duffy

답변:


70

기본적으로 전달 된 모든 명령 줄 인수 entrypoint.sh를 사용하여 명령으로 실행합니다. 의도는 기본적으로 "이 .sh 스크립트에서 모든 작업을 수행 한 다음 동일한 쉘에서 사용자가 명령 줄에서 전달하는 명령을 실행합니다"입니다.

보다:


1
또한 exec "$@"현재 실행중인 프로세스를 전달 된 인수에 대해 생성 된 새 프로세스로 대체합니다. Docker 신호에 중요 : stackoverflow.com/a/32261019/99717
Hawkeye Parker

34

set -e실행중인 명령이 0이 아닌 종료 코드로 종료되는 경우 즉시 종료하도록 셸 옵션을 설정합니다. 스크립트는 실패한 명령의 종료 코드와 함께 반환됩니다. bash man 페이지에서 :

-e 설정 :

파이프 라인 (단일 간단한 명령으로 구성 될 수 있음), 목록 또는 복합 명령 (위의 SHELL GRAMMAR 참조)이 0이 아닌 상태로 종료되면 즉시 종료합니다. 실패한 명령이 while 또는 until 키워드 바로 뒤에 오는 명령 목록의 일부, if 또는 elif 예약어 다음에 오는 테스트의 일부, && 또는 ||에서 실행되는 명령의 일부인 경우 쉘은 종료되지 않습니다. 마지막 && 또는 || 뒤에 오는 명령, 파이프 라인에 있지만 마지막 명령을 제외한 모든 명령 또는 명령의 반환 값이!로 반전되는 경우. -e가 무시되는 동안 명령이 실패하여 서브 쉘 이외의 복합 명령이 0이 아닌 상태를 리턴하면 쉘이 종료되지 않습니다. ERR에 대한 트랩이 설정된 경우 쉘이 종료되기 전에 실행됩니다.

-e가 무시되는 컨텍스트에서 복합 명령 또는 쉘 함수가 실행되는 경우, 복합 명령 또는 함수 본문 내에서 실행 된 명령은 -e가 설정되고 명령이 a 실패 상태. -e가 무시되는 컨텍스트에서 실행하는 동안 복합 명령 또는 쉘 함수가 -e를 설정하면 해당 설정은 복합 명령 또는 함수 호출을 포함하는 명령이 완료 될 때까지 영향을주지 않습니다.


exec "$@"일반적으로 진입 점을 통과 한 다음 docker 명령을 실행하는 데 사용됩니다. 현재 실행중인 셸을 "$@"가리키는 명령으로 대체합니다 . 기본적으로 해당 변수는 명령 줄 인수를 가리 킵니다.

entrypoint.sh를 가리키는 진입 점이있는 이미지가 있고 컨테이너를로 docker run my_image server start실행 entrypoint.sh server start하면 컨테이너에서 실행 되는 것으로 변환됩니다 . exec 라인 entrypoint.sh에서 pid 1로 실행되는 쉘은 자신을 명령으로 대체합니다 server start.

이것은 신호 처리에 중요합니다. 사용하지 않고 execserver start위의 예에서 다른 PID로 실행 것이고, 그것이 종료 후, 당신은 당신의 쉘 스크립트로 반환합니다. pid 1의 쉘을 사용하면 SIGTERM이 기본적으로 무시됩니다. 즉 docker stop, 컨테이너로 보내는 우아한 중지 신호 는 server프로세스에서 수신되지 않습니다 . 10 초 후 (기본적으로) docker stop정상 종료를 포기하고 앱을 강제로 종료하는 SIGKILL을 전송하지만 잠재적 인 데이터 손실 또는 네트워크 연결이 끊어지면 앱 개발자가 신호를 수신하면 코드를 작성할 수 있습니다. 또한 컨테이너가 정지하는 데 항상 10 초가 걸립니다.

쉘 명령이 좋아에주의 shift하고 set --, 당신의 값을 변경할 수 있습니다 "$@". 예를 들어 /bin/sh -c "..."다음은 도커의 쉘 구문을 사용하는 경우 나타날 수있는 명령에서을 제거하는 스크립트의 짧은 부분입니다 CMD.

# convert `/bin/sh -c "server start"` to `server start`
if [ $# -gt 1 ] && [ x"$1" = x"/bin/sh" ] && [ x"$2" = x"-c" ]; then
  shift 2
  eval "set -- $1"
fi

....

exec "$@"

1
노후화 를 표시 하는 POSIX test사양을 참조하십시오 -a. [ "$#" -gt 1 ] && [ "$1" = /bin/sh ]올바른 대체입니다 ( x"$1"구식이 아닌 구문 만 사용하는 경우 해커 가 필요 없음 ).
Charles Duffy

또한 문자열을 구문 분석하는 shift 2; set -- $1방법과 전혀 동일하지 않습니다 eval. 고려 /bin/sh -c 'printf "%s\n" "hello world" "goodbye world"'당신은 콘크리트 테스트 케이스를 원하고 볼 경우, 인수에 문자열을 변환 할 때 배쉬 구문 분석 따옴표하지 않습니다 .
Charles Duffy

@CharlesDuffy 노후화 옵션에 대한 팁을 주셔서 감사합니다.이 실수를 다시 할 것이라고 확신합니다. 오래된 습관은 힘들어집니다. 을 사용하여 eval여전히 /bin/sh -c문자열에 대한 동작을 미러링하고 싶지만 누락 된 것이 있으면 알려주십시오.
BMitch

30

set -e -명령이 실패하면 스크립트 종료 (0이 아닌 값)

exec "$@"-입력 변수를 리디렉션합니다. 자세한 내용은 여기를 참조 하십시오.


"입력 변수를 리디렉션 할 것"입니까? 뭐라고? exec확실히 리디렉션을 수행하는 사용 모드가 있지만 이것은 그 모드가 아닙니다.
Charles Duffy
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.