리눅스 서브 쉘과 Crontab

greenTea·2024년 10월 30일
post-thumbnail

문제

회사에서 crontab으로 쉘 스크립트를 작업하던 중, 예상대로 실행되지 않아 많은 어려움을 겪었습니다.

구글링을 통해 찾아보니, crontab에서는 환경이 다르기 때문에 설정을 해줘야 한다는 내용의 글들을 보았지만, 실제로 로그를 확인해 본 결과 다른 이유가 원인이라는 것을 알게 되었습니다.

아래는 문제 상황을 재현한 간단한 스크립트입니다.

문제의 스크립트

#!/bin/bash

# 부모 셸에서 변수 선언 (export하지 않음)
password="1234"

# 서브 셸에서 my_var 출력 시도
bash -c 'echo "password: $password"'

이 스크립트를 실행하면 결과는 다음과 같이 비어 있는 출력입니다.

password:

문제의 원인

이유는 간단합니다.
스크립트에서 작성한 password 변수는 자식 쉘이나 프로세스에 전달되지 않기 때문입니다.

이를 아래와 같이 변경하면 원하는 결과를 얻을 수 있습니다.

#!/bin/bash

# 부모 셸에서 변수 선언 (export하지 않음)
export password="1234"

# 서브 셸에서 my_var 출력 시도
bash -c 'echo "password: $password"'
password: 1234

설명: password=1234로 지정한 경우, 해당 변수는 현재 셸에만 적용되므로 서브 셸에서는 인식되지 않습니다. 그러나 export를 사용해 password를 환경 변수로 만들면, 해당 셸의 하위 프로세스(서브 셸)에서도 이 값을 인식할 수 있어 변수가 전달됩니다.

실제 문제 상황 예시

실제 문제로 겪었던 스크립트는 아래와 같습니다.

PGPASSWORD=...
psql -h ...

처음에는 ./psql-connect.sh처럼 직접 스크립트를 실행했기에 문제가 없었습니다. 그러나 crontab에 추가하고 나서는 다른 상황이 발생했습니다.

예시 상황

  • echo $PGPASSWORD 결과: 1234
  • ./psql-connect.sh 실행 시: 로컬에서 설정한 값이 아닌 환경 변수 값이 적용되는 것으로 오해함

크론탭에서는 기존 환경 변수 값이 적용되지 않으므로, 크론탭의 환경과 로그인 셸의 환경이 다르다는 것을 알게 되었습니다.

문제를 해결한 방법 (예시 스크립트)

bashrcexport local3="local 3333333333" 추가 -> 이를 통해 환경 변수 값을 cronjob 실행시 읽어오는지를 확인

크론탭 설정

crontab에 추가한 스크립트는 다음과 같습니다.

#!/bin/bash

local1="local 1111111111"
export local2="lcoal 2222222222"

echo "local1: $local1"
echo "local2: $local2"
echo "local3: $local3"

크론탭 실행 결과

Oct 30 12:26:01 test-vm CROND[4441]: (testuser) CMDOUT (local1: local 1111111111)
Oct 30 12:26:01 test-vm CROND[4441]: (testuser) CMDOUT (local2: lcoal 2222222222)
Oct 30 12:26:01 test-vm CROND[4441]: (testuser) CMDOUT (local3: )

여기서, local3 변수는 crontab 환경에서 적용되지 않았습니다.

수정 방법

crontab에서 초기화 파일을 직접 소스하여 변수를 적용했습니다.

#!/bin/bash

# .bashrc 파일을 소스하여 환경 변수 로드
. ~/.bashrc

local1="local 1111111111"
export local2="lcoal 2222222222"

echo "local1: $local1"
echo "local2: $local2"
echo "local3: $local3"

수정 후 실행 결과

Oct 30 12:45:01 test-vm CROND[12429]: (testuser) CMDOUT (local1: local 1111111111)
Oct 30 12:45:01 test-vm CROND[12429]: (testuser) CMDOUT (local2: lcoal 2222222222)
Oct 30 12:45:01 test-vm CROND[12429]: (testuser) CMDOUT (local3: lcoal 3333333333333333333333)

이제 local3 변수도 정상적으로 출력되는 것을 확인할 수 있었습니다.

추가 설명

crontab에서 초기화 파일이 자동으로 로드되지 않는 이유는 크론탭이 비로그인, 비인터랙티브 셸 환경에서 실행되기 때문입니다. 따라서 .bashrc.bash_profile 같은 초기화 파일을 명시적으로 로드하지 않으면, 스크립트 내에서 정의하지 않은 환경 변수는 인식되지 않습니다.

참고 자료

profile
greenTea입니다.

0개의 댓글