SAS 프로그램 안에서 파일을 다른 서버로 보내거나 셸 스크립트를 돌려야 할 때 쓸 수 있는 두 가지 경로와, 각각이 막히는 지점을 정리한다.
FILENAME 문의 SFTP 액세스 메서드는 자체 SFTP 구현이 아니라 운영체제의 sftp 명령을 배치 모드로 호출하는 껍데기다. 그래서 대화형 비밀번호 입력을 할 수 없고, 비밀번호를 넘기는 옵션 자체가 존재하지 않는다.
ERROR: invalid option name PASS.
ERROR: invalid option name PASSWORD.
pass= 든 password= 든 없는 옵션이므로 철자를 바꿔 가며 시도할 일이 아니다. 인증은 SSH 키로 한다.
# SAS 를 실행하는 계정으로 수행한다
ssh-keygen -t ed25519 -f ~/.ssh/id_sas -N ''
ssh-copy-id -i ~/.ssh/id_sas.pub <USER>@<REMOTE_HOST>
ssh -i ~/.ssh/id_sas <USER>@<REMOTE_HOST> true
호스트 키가 known_hosts 에 없으면 배치 모드에서 그대로 실패한다. 반드시 한 번 접속해 등록해 둔다.
filename remote sftp '<REMOTE_PATH>/abc.sas'
host='<REMOTE_HOST>'
user='<USER>'
identity='/home/sasuser/.ssh/id_sas'
cd='<REMOTE_DIR>';
data _null_;
infile '/opt/sas/sasdata/fileupload/abc.sas';
file remote;
input;
put _infile_;
run;
읽어 오는 방향도 같은 방식이다. file 과 infile 의 자리를 바꾸면 된다.
전송 주체는 SAS 서버 프로세스를 실행하는 OS 계정이다. SAS Studio 로 접속한 사용자 계정이 아니다. 키는 그 계정의 홈 디렉터리에 있어야 하고, identity= 에 절대경로로 지정하는 편이 확실하다.
Azure Blob Storage 같은 객체 스토리지를 SFTP 로 붙이려는 시도는 대체로 실패한다. SFTP 엔드포인트를 별도로 활성화한 계정이 아니면 프로토콜 자체가 열려 있지 않고, 열려 있더라도 계정·컨테이너·경로 규칙이 일반 SFTP 서버와 다르다. 전용 CLI 를 쓰고 그것을 SAS 에서 호출하는 편이 단순하다.
azcopy copy '/opt/sas/sasdata/out.csv' \
'https://<ACCOUNT>.blob.core.windows.net/<CONTAINER>/out.csv?<SAS_TOKEN>'
options noxwait noxsync;
x '/opt/sas/scripts/sftp_upload.sh';
data _null_;
call system('/opt/sas/scripts/sftp_upload.sh');
run;
X 는 전역 문장이라 데이터 스텝 밖에서, CALL SYSTEM 은 데이터 스텝 안에서 쓴다. 매크로에서 호출할 때는 %SYSEXEC 를 쓴다.
두 방법 모두 XCMD 시스템 옵션이 켜져 있어야 한다. 꺼져 있으면 다음이 나온다.
ERROR: Shell escape is not valid in this SAS session.
proc options option=xcmd; run;
SAS Studio 나 Viya 의 컴퓨트 세션에서는 보안상 NOXCMD 로 막아 둔 경우가 많다. 관리자만 바꿀 수 있고, 세션 옵션이 아니라 서버 기동 옵션이다. 막혀 있다면 셸 실행 대신 FILENAME PIPE 로 명령 출력을 읽는 방법도 같은 이유로 막혀 있을 가능성이 높으므로, 애초에 SAS 밖에서 스케줄러로 돌리는 구조로 바꾸는 편이 낫다.
ERROR: 논리적 이름이 올바르지 않습니다 는 FILENAME 이 가리키는 경로가 없거나 SAS 서버 계정이 그 경로를 읽지 못할 때 나온다. 파일이 있는지 그리고 서버 계정 기준으로 접근 가능한지를 확인한다 — 작업자의 계정 기준이 아니다.
여러 디렉터리를 돌며 파일을 옮기는 스크립트는 SAS 안에 넣지 말고 별도 .sh 로 두고 호출한다. 그래야 SAS 로그가 아니라 셸 종료 코드로 성공 여부를 판정할 수 있다.
#!/bin/bash
set -euo pipefail
SRC_BASE=/opt/sas/sasdata/fileupload
DST=<REMOTE_DIR>
KEY=/home/sasuser/.ssh/id_sas
for d in a b c; do
src="$SRC_BASE/$d"
[ -d "$src" ] || { echo "skip $src"; continue; }
find "$src" -maxdepth 1 -type f -print0 |
while IFS= read -r -d '' f; do
sftp -b - -i "$KEY" "<USER>@<REMOTE_HOST>" <<EOF
cd $DST/$d
put "$f"
EOF
done
done
sftp -b 는 배치 모드라 비밀번호를 물어보지 않고, 키 인증이 안 되면 바로 실패한다. 연결 여부를 미리 확인하고 싶으면 실제 전송 전에 한 번 두드려 본다.
if ! ssh -o BatchMode=yes -o ConnectTimeout=5 -i "$KEY" "<USER>@<REMOTE_HOST>" true; then
echo "SFTP 연결 실패" >&2
exit 1
fi
"파일이 이동되지 않는다" 는 증상은 대개 put 이 성공했는데 원본을 지우지 않은 것이거나, 원격 디렉터리가 없어 cd 에서 실패한 뒤 나머지가 무시된 것이다. sftp 의 종료 코드는 배치 스크립트 중간 실패를 항상 반영하지 않으므로, 전송 후 원격에서 파일 존재를 확인하는 단계를 넣는다.