리눅스 crontab에 걸어둔 파일이 작동하지 않는 경우 일반적인 원인은 환경변수이다. crontab은 nologin shell로 실행되기 때문에 PATH 등 /etc/profile에 걸어둔 내용들이 적용되지 않는다. 따라서 특정 위치에 있는 명령어를 절대경로로 적어두지 않은 경우 crontab이 PATH에서 해당 명령어를 찾지 못해 실패하게 된다.


이를 해결하기 위한 방법으로 아래 4가지 정도가 있다.


1. 명령어를 절대경로로 사용한다.

- ex) java 대신 /app/jdk/bin/java


2. bash 스크립트 최상단에 #!/bin/bash 뒤에 -l 을 붙인다. (로그인)

- ex) #!/bin/bash 대신 #!/bin/bash -l


3. bash 스크립트 내부에서 /etc/profile을 한번 불러들인다.

- ex) source /etc/profile 또는 . /etc/profile


4. crontab에 등록할때 bash -lc를 활용한다. (로그인)

- ex) * * * * * bash -lc /tmp/hello.py



그런데 위 4가지 방법으로도 해결되지 않는 문제가 있다. 즉 환경변수와 무관한 문제인데 바로 crontab 내부에서 % 문자열을 사용했을 경우이다.


아래와 같이 오늘 날짜를 파일명으로 해서 log로 남기고 싶은데



해보면 알겠지만 동작하지 않는다.

혹시나 싶어 double or single quotation을 붙여봐도 역시나 작동하지 않는다.




혹시나 싶어 $(command) 대신 `command` 방식으로 명령어를 입력해도 안되는건 동일하다.



원인은 바로 % 문자가 crontab 내부에서 newline으로 해석되기 때문이다.


The "sixth" field (the rest of the line) specifies the command

to be run.  The entire command portion of the line,  up  to  a

newline  or a "%" character, will be executed by /bin/sh or by

the shell specified in the SHELL variable of the cronfile.   A

"%"  character in the command, unless escaped with a backslash

(\), will be changed into newline  characters,  and  all  data

after  the  first  %  will  be sent to the command as standard

input.


따라서 아래와 같이 %를 \ (backslash)로 escape 시켜주면 해결된다.