소개
유용한 배치 애플리케이션은 이전 세션에 남은 DataFrame이나 임시 뷰에 의존하지 않고 명시적인 입력과 출력이 있는 저장 프로그램에서 실행되어야 합니다. 준비된 일일 판매 프로그램을 별도 프로세스로 제출하고 저장된 결과와 실행 증거를 모두 확인합니다.
spark-submit은 Spark 애플리케이션 실행 도구입니다. 실행 master, Python 프로그램과 프로그램의 입력 및 출력 인수를 제공합니다. 스크립트는 의도적으로 외부 master 설정이 실행을 제어하도록 합니다. 보고 로직은 이미 배운 자료형 읽기, paid 필터, 십진수 금액과 그룹화를 반복합니다. 인수 처리가 제공되므로 제출과 안전한 재실행에 집중할 수 있습니다.
이 독립 실습은 유효한 CSV 데이터 두 벌과 전체 프로그램을 제공합니다. 로그와 종료 코드를 확인하고 입력 경로를 바꾸며 입력 누락과 기존 출력 충돌을 구분합니다. 원격 클러스터, 패키징, 스케줄러, Hive나 이전 프로세스 상태는 필요하지 않습니다. 터미널을 사용하세요.
명시적인 인수로 준비된 프로그램 제출하기
이 단계에서는 첫 데이터를 독립 애플리케이션으로 처리합니다. 원본과 제공된 프로그램을 살펴봅니다.
cd /home/labex/project
cat /home/labex/project/data/orders.csv
cat /home/labex/project/sales_batch.py
파서는 이미 input_path, output_path와 선택적 --overwrite를 받습니다. argparse를 구현할 필요는 없습니다. 첫 위치 인수는 항상 입력이고 두 번째는 출력입니다. SparkSession 빌더는 master를 호출하지 않으므로 실행 도구의 --master 설정이 실행을 제어합니다.
명령을 왼쪽부터 읽으세요. spark-submit 옵션은 Python 파일 이름 앞에 두고 파일 이름 뒤의 인수는 애플리케이션에 전달합니다. 셸이 대괄호를 문자 그대로 처리하도록 local[2]를 따옴표로 묶습니다. >는 일반 출력을 저장하고 2>&1은 오류 출력을 같은 로그로 보냅니다.
spark-submit --master 'local[2]' /home/labex/project/sales_batch.py /home/labex/project/data/orders.csv /home/labex/project/output/run-1 > /home/labex/project/output/run-1-job.log 2>&1
다른 터미널 명령을 실행하기 전에 즉시 종료 상태를 기록하세요. $?는 이전 명령의 상태입니다. 0은 성공, 0이 아니면 실패입니다. printf는 그 값과 줄바꿈을 로컬 상태 파일에 씁니다.
printf '%s\n' "$?" > /home/labex/project/output/run-1-exit-status.txt
cat /home/labex/project/output/run-1-exit-status.txt
0이 예상됩니다. 드라이버 로그 끝부분을 읽습니다.
tail -n 30 /home/labex/project/output/run-1-job.log
Master: local[2], 실제 애플리케이션 ID, 선택한 입력·출력 경로와 보고서 날짜를 찾으세요. ID는 달라집니다. 보고서는 10월 14일 / 2 / 45.00과 10월 15일 / 2 / 80.00이어야 합니다. 종료 코드 0과 올바른 실제 Parquet 결과가 함께 있는 것이 안심되는 로그 한 줄보다 강한 증거입니다.
프로그램은 자체 세션을 만들고 종료합니다. 이전 수업의 뷰나 Python 변수를 재사용하지 않았습니다.
새 프로세스에서 입력 바꾸기
이 단계에서는 제공된 경로에서 프로그램이 결과를 도출함을 증명합니다. 두 번째 데이터를 확인합니다.
cat /home/labex/project/data/new-orders.csv
10월 16일에 금액 30.00과 25.00인 결제 완료 주문 두 건 및 대기 주문 하나가 있습니다. 개수 2, 매출 55.00인 보고서 한 행을 예상하세요. 첫 출력을 유지하고 새 파일을 별도 대상에 제출합니다.
spark-submit --master 'local[2]' /home/labex/project/sales_batch.py /home/labex/project/data/new-orders.csv /home/labex/project/output/run-2 > /home/labex/project/output/run-2-job.log 2>&1
printf '%s\n' "$?" > /home/labex/project/output/run-2-exit-status.txt
cat /home/labex/project/output/run-2-exit-status.txt
tail -n 30 /home/labex/project/output/run-2-job.log
상태 0과 예상한 10월 16일 결과가 있어야 합니다. 실제 애플리케이션 ID는 첫 프로세스와 다릅니다. 프로그램이 새 경로를 읽고 자체 세션을 만들었으며 남아 있는 뷰는 필요하지 않았습니다.
run-1과 run-2가 모두 남아 각 입력과 결과의 관계를 확인할 수 있습니다. 기억한 답을 나타내려고 원본 파일을 바꾸지 마세요.
입력 누락과 기존 출력을 따로 진단하기
이 단계에서는 데이터를 삭제하지 않고 서로 다른 두 경로 실패를 기록합니다. 먼저 없는 입력을 제출합니다. 다음 명령은 실패하는 것이 정상입니다.
spark-submit --master 'local[2]' /home/labex/project/sales_batch.py /home/labex/project/data/missing-orders.csv /home/labex/project/output/unused-missing-input > /home/labex/project/output/missing-input.log 2>&1
로그를 보기 전에 상태를 즉시 기록합니다.
printf '%s\n' "$?" > /home/labex/project/output/missing-input-exit-status.txt
cat /home/labex/project/output/missing-input-exit-status.txt
tail -n 25 /home/labex/project/output/missing-input.log
0이 아닌 상태와 missing-orders.csv를 가리키는 경로 없음 진단이 예상됩니다. 입력 경로를 바로잡으면 해결됩니다. master를 바꾸거나 클러스터를 다시 만들 문제가 아닙니다.
스크립트의 기본 errorifexists 모드도 기존 대상을 보호합니다. 알고 있는 입력을 이미 완료된 run-1 경로에 실행해 보세요. 다음 명령은 실패하는 것이 정상입니다.
spark-submit --master 'local[2]' /home/labex/project/sales_batch.py /home/labex/project/data/orders.csv /home/labex/project/output/run-1 > /home/labex/project/output/existing-output.log 2>&1
printf '%s\n' "$?" > /home/labex/project/output/existing-output-exit-status.txt
cat /home/labex/project/output/existing-output-exit-status.txt
tail -n 25 /home/labex/project/output/existing-output.log
0이 아닌 상태와 출력이 이미 있다는 진단이 예상됩니다. 입력 누락과는 다르며 앞서 성공한 보고서는 온전히 남아 있어야 합니다.
올바른 원본과 새 출력 디렉터리로 보존을 우선하는 수정을 합니다.
spark-submit --master 'local[2]' /home/labex/project/sales_batch.py /home/labex/project/data/orders.csv /home/labex/project/output/run-3 > /home/labex/project/output/run-3-job.log 2>&1
printf '%s\n' "$?" > /home/labex/project/output/run-3-exit-status.txt
cat /home/labex/project/output/run-3-exit-status.txt
tail -n 25 /home/labex/project/output/run-3-job.log
성공과 원래 두 일일 합계가 예상됩니다. 새 대상은 원본 파일이나 넓은 출력 트리를 제거하지 않고 앞선 두 데이터와 실패 증거를 유지합니다.
의도한 파생 스냅샷을 명시적으로 다시 만들기
이 단계에서는 알고 있는 전체 스냅샷의 교체를 의도적으로 선택합니다. 선택적 --overwrite 인수는 이미 구현되어 있으며 이 프로그램의 대상 쓰기 모드만 overwrite로 바꿉니다. 입력, 다른 결과 경로나 Spark의 외부 master는 바꾸지 않습니다.
같은 원본에서 지정한 전체 파생 결과를 다시 만들려는 경우 사용하세요. 여기서는 run-1이 그 스냅샷이며 다른 실행과 원본 입력은 분리되어 남습니다.
spark-submit --master 'local[2]' /home/labex/project/sales_batch.py /home/labex/project/data/orders.csv /home/labex/project/output/run-1 --overwrite > /home/labex/project/output/overwrite-job.log 2>&1
printf '%s\n' "$?" > /home/labex/project/output/overwrite-exit-status.txt
cat /home/labex/project/output/overwrite-exit-status.txt
tail -n 30 /home/labex/project/output/overwrite-job.log
상태 0, Write mode: overwrite와 같은 두 보고서 행이 예상됩니다. 새 프로세스는 날짜 중복을 더하지 않고 스냅샷을 교체합니다. 애플리케이션 ID는 첫 실행과 다르고 로그도 자체 파일 이름을 사용합니다.
기존 출력에 대한 두 가지 올바른 대응을 연습했습니다. 두 버전 보존이 중요하면 새 경로를 선택하고, 교체가 목적이면 알고 있는 파생 스냅샷을 명시적으로 재생성합니다. 입력 경로 오류에는 여전히 올바른 입력이 필요합니다. 덮어쓰기는 입력 누락의 해결책이 아닙니다. 이러한 제출 및 재실행 습관은 마지막 재사용 가능 판매 파이프라인 도전 과제를 준비합니다.
요약
매개변수화된 Spark 애플리케이션을 독립 프로세스로 실행하고 실제 상태 및 로그를 기록했으며 서로 다른 입력의 결과를 검증했습니다. 입력 누락과 기존 출력 충돌을 구분하고 새 대상 또는 명시적 스냅샷 교체를 선택했습니다. 마지막 도전 과제에서는 이러한 제출 습관을 정제, 정보 추가, 집계와 파티션 출력에 결합합니다.



