쉘 면접 질문 및 답변

ShellBeginner
지금 연습하기

소개

Shell 면접 질문 및 답변에 대한 포괄적인 가이드에 오신 것을 환영합니다! 면접을 준비 중이거나 기존 기술을 연마하고 싶거나 단순히 쉘 지식의 폭에 대해 궁금한 점이 있다면, 이 문서는 여러분의 궁극적인 자료가 될 것입니다. 기본 개념과 고급 스크립팅부터 시나리오 기반 문제 해결 및 역할별 과제까지 모든 것을 다루어 어떤 기술 토론에도 잘 대비할 수 있도록 보장합니다. 실용적인 작업, 문제 해결 기법, 모범 사례 및 필수 보안 고려 사항을 탐색하여 쉘 스크립팅 및 명령줄 숙련도에 대한 전문성을 자신 있게 보여줄 수 있도록 하십시오.

SHELL

기본 쉘 개념 및 명령어

하드 링크 (hard link) 와 심볼릭 링크 (soft link) 의 차이점은 무엇인가요?

답변:

하드 링크는 파일의 inode 를 직접 가리키므로, 동일한 파일 데이터에 대한 추가적인 디렉토리 항목입니다. 심볼릭 링크 (symlink) 는 다른 파일이나 디렉토리에 대한 경로를 포함하는 특수 파일입니다. 하드 링크는 파일 시스템을 넘나들 수 없으며 디렉토리를 링크할 수 없는 반면, 심볼릭 링크는 가능합니다.


PATH 환경 변수의 목적을 설명해주세요.

답변:

PATH 환경 변수는 쉘이 전체 경로 없이 명령을 입력했을 때 실행 가능한 명령을 검색하는 디렉토리들의 콜론으로 구분된 목록입니다. 이를 통해 사용자는 /bin/ls 또는 /usr/bin/grep과 같이 전체 경로를 지정하지 않고 ls 또는 grep과 같은 명령을 실행할 수 있습니다.


표준 출력 (standard output) 과 표준 오류 (standard error) 를 별도의 파일로 리디렉션하는 방법은 무엇인가요?

답변:

command > output.txt 2> error.txt를 사용하여 표준 출력 (1) 과 표준 오류 (2) 를 별도의 파일로 리디렉션할 수 있습니다. 이렇게 하면 성공적인 출력은 output.txt로, 오류 메시지는 error.txt로 전송됩니다.


execsource (또는 .) 명령어의 차이점은 무엇인가요?

답변:

exec는 현재 쉘 프로세스를 지정된 명령으로 대체하므로 원래 쉘이 종료됩니다. source (또는 .) 는 현재 쉘 환경에서 스크립트를 실행하므로 스크립트에서 정의된 변수나 함수가 현재 쉘 환경의 일부가 됩니다.


grep 명령어의 기능을 설명하고 기본적인 예시를 제공해주세요.

답변:

grep (Global Regular Expression Print) 은 텍스트 파일에서 패턴을 검색하는 데 사용됩니다. 주어진 정규 표현식과 일치하는 줄을 출력합니다. 예를 들어, grep 'error' logfile.txtlogfile.txt에서 'error'라는 단어를 포함하는 모든 줄을 표시합니다.


현재 디렉토리 및 하위 디렉토리에서 10MB 보다 큰 모든 파일을 찾는 방법은 무엇인가요?

답변:

find 명령어를 사용할 수 있습니다: find . -type f -size +10M. 이 명령어는 현재 디렉토리 (.) 에서 파일 (-type f) 중 10MB(10M) 보다 큰 (+) 파일을 검색합니다.


쉘에서 '파이핑 (piping)' 개념을 설명해주세요.

답변:

파이핑 (|) 은 한 명령어의 표준 출력을 다른 명령어의 표준 입력에 연결하는 메커니즘입니다. 이를 통해 여러 명령어를 연결하여 복잡한 작업을 수행할 수 있으며, 한 명령어의 출력이 다음 명령어의 입력이 됩니다.


쉘에서 ~ (틸드) 문자의 중요성은 무엇인가요?

답변:

~ (틸드) 문자는 현재 사용자의 홈 디렉토리로 확장되는 축약 표기법입니다. 예를 들어, cd ~/documents는 사용자의 홈 디렉토리 내의 documents 폴더로 디렉토리를 변경합니다.


압축된 gzipped 파일의 내용을 압축 해제하지 않고 보는 방법은 무엇인가요?

답변:

zcat 명령어를 사용할 수 있습니다. 예를 들어, zcat file.gz는 디스크에 압축 해제된 파일을 생성하지 않고 file.gz의 압축되지 않은 내용을 표준 출력으로 표시합니다.


chmod 명령어의 목적은 무엇인가요?

답변:

chmod (change mode) 는 파일 및 디렉토리 권한을 변경하는 데 사용됩니다. 파일에 대한 읽기, 쓰기 또는 실행 권한을 누가 가질 수 있는지 제어합니다. 권한은 기호 모드 (예: u+x) 또는 8 진수 표기법 (예: 755) 을 사용하여 설정할 수 있습니다.


고급 스크립팅 및 프로그래밍

'source'와 스크립트를 직접 실행하는 것 (예: './script.sh') 의 차이점을 설명해주세요.

답변:

스크립트를 소싱하는 것 (source script.sh 또는 . script.sh) 은 현재 쉘 환경에서 실행되므로 정의된 변수나 함수가 현재 쉘의 일부가 됩니다. 직접 실행하는 것 (./script.sh) 은 새로운 서브쉘에서 스크립트를 실행하므로 환경 변경 사항이 부모 쉘로 다시 전파되지 않습니다.


쉘 스크립트에서 오류와 종료 코드를 처리하는 방법은 무엇인가요?

답변:

오류는 일반적으로 $?를 사용하여 명령의 종료 상태를 확인하여 처리합니다. 0 이 아닌 종료 상태는 오류를 나타냅니다. 명령이 실패하면 즉시 종료하려면 set -e를 사용하거나, 종료 시 또는 특정 신호 수신 시 명령을 실행하려면 trap을 사용할 수 있습니다.


스크립트 시작 부분에 있는 'set -euxo pipefail'의 목적을 설명해주세요.

답변:

set -e는 명령이 0 이 아닌 상태로 종료되면 즉시 종료합니다. set -u는 설정되지 않은 변수를 오류로 처리합니다. set -x는 실행되는 명령과 해당 인수를 출력합니다. set -o pipefail은 파이프라인에서 마지막 명령의 종료 상태만 반환하는 대신, 0 이 아닌 상태를 반환한 마지막 명령의 종료 상태를 반환하도록 합니다.


쉘 스크립트에 인수를 전달하고 액세스하는 방법은 무엇인가요?

답변:

인수는 스크립트 이름 뒤에 직접 전달됩니다 (예: ./script.sh arg1 arg2). 스크립트 내에서는 위치 매개변수를 사용하여 액세스합니다. 첫 번째 인수는 $1, 두 번째 인수는 $2 등입니다. $#는 전체 인수 수를 제공하고, $@는 모든 인수를 개별 단어로 확장합니다.


'here document' 개념을 설명하고 간단한 예시를 제공해주세요.

답변:

'here document'를 사용하면 임시 파일을 생성하지 않고도 여러 줄의 입력을 키보드로 입력하는 것처럼 명령에 전달할 수 있습니다. << DELIMITER로 표시됩니다. 예시: cat << EOF Hello World EOF.


'trap' 명령어는 무엇이며 언제 사용해야 하나요?

답변:

trap 명령어는 쉘이 신호 (예: Ctrl+C 의 SIGINT, 종료의 SIGTERM) 를 받거나 쉘이 종료될 때 명령을 실행할 수 있도록 합니다. 임시 파일을 제거하는 것과 같이 정리 작업에 일반적으로 사용되며, 스크립트가 중단되더라도 리소스가 해제되도록 보장합니다.


Bash 에서 산술 연산을 수행하는 방법은 무엇인가요?

답변:

Bash 에서의 산술 연산은 일반적으로 ((...)) 또는 $[...]를 사용하여 수행됩니다. 예를 들어, result=$((5 + 3)) 또는 result=$[5 + 3]입니다. expr 명령어도 사용할 수 있지만, 간단한 정수 산술에는 더 오래되고 효율성이 떨어집니다.


쉘 스크립트를 디버깅하는 방법을 설명해주세요.

답변:

디버깅은 스크립트 시작 부분에 set -x를 추가하거나 bash -x script.sh를 실행하여 수행할 수 있습니다. 이렇게 하면 각 명령이 실행되기 전에 출력됩니다. 또한 echo 문을 삽입하여 실행의 다른 단계에서 변수 값을 출력할 수도 있습니다.


조건 표현식에서 [[[의 차이점은 무엇인가요?

답변:

[[는 POSIX 호환 [ (외부 명령) 보다 더 고급 기능을 제공하는 Bash 키워드입니다. [[는 패턴 매칭 (=~), 논리 연산자 (&&, ||) 를 지원하며 단어 분할 및 경로명 확장을 방지하여 문자열 및 파일 테스트에 더 안전하고 강력합니다.


Bash 에서 함수를 작성하고 호출하는 방법은 무엇인가요?

답변:

함수는 function_name() { commands; } 또는 function function_name { commands; }를 사용하여 정의됩니다. 함수 이름만 입력하여 호출합니다. 인수는 스크립트에 전달되는 것처럼 함수 내에서 위치 매개변수 ($1, $2 등) 를 사용하여 전달됩니다. 예시: my_func() { echo $1; }; my_func 'hello'.


시나리오 기반 문제 해결

현재 디렉토리 및 하위 디렉토리에서 10MB 보다 큰 모든 파일을 찾은 다음, 해당 경로와 크기를 사람이 읽기 쉬운 형식으로 나열해야 합니다. 어떻게 해야 할까요?

답변:

find . -type f -size +10M -exec du -h {} \;를 사용합니다. find는 파일을 찾고, -type f는 파일을 지정하며, -size +10M은 크기로 필터링하고, -exec du -h {} \;는 찾은 각 파일에 대해 du -h를 실행합니다.


로그 파일 /var/log/app.log가 빠르게 증가하고 있습니다. 지난 24 시간 동안 'ERROR'라는 단어를 포함하는 모든 줄을 추출하여 새 파일 errors_today.log에 저장해야 합니다. 로그 항목은 타임스탬프로 시작한다고 가정합니다.

답변:

먼저 24 시간 전의 타임스탬프를 결정합니다. 그런 다음 awk 또는 sed와 함께 grep을 사용하여 필터링합니다. 예시: grep 'ERROR' /var/log/app.log | awk '$1 >= "$(date -d '24 hours ago' +'%Y-%m-%d')"' > errors_today.log. 사용 가능한 경우 logrotate 또는 journalctl을 사용하면 더 강력한 솔루션이 될 수 있습니다.


Name,Age,City 열이 있는 CSV 파일 data.csv가 있습니다. Age별로 내림차순, Name별로 오름차순으로 정렬한 다음 NameCity만 출력해야 합니다.

답변:

sortcut, awk를 사용합니다. (head -n 1 data.csv; tail -n +2 data.csv | sort -t',' -k2nr -k1n)로 정렬합니다. 그런 다음 cut -d',' -f1,3 또는 awk -F',' '{print $1 "," $3}'로 열을 선택합니다. 결합: (head -n 1 data.csv; tail -n +2 data.csv | sort -t',' -k2nr -k1) | awk -F',' '{print $1 "," $3}'.


백그라운드에서 myscript.sh 스크립트가 실행 중인데 멈춘 것으로 의심됩니다. 상태를 확인하는 방법과 응답이 없는 경우 정상적으로 종료하고, 필요한 경우 강제로 종료하는 방법은 무엇인가요?

답변:

ps aux | grep myscript.sh로 상태를 확인합니다. 정상적으로 종료하려면 kill <PID>를 사용합니다. 응답이 없으면 강제 종료를 위해 kill -9 <PID>를 사용합니다. 정리 작업을 허용하기 위해 항상 정상 종료를 먼저 시도해야 합니다.


/etc 디렉토리의 백업을 생성하고, gzip을 사용하여 압축하고, /tmp/etc_backup_YYYYMMDD.tar.gz에 저장해야 합니다. 이 작업을 어떻게 자동화할 수 있나요?

답변:

targzip을 사용합니다. tar -czf /tmp/etc_backup_$(date +%Y%m%d).tar.gz /etc. 이 명령어는 날짜가 포함된 이름으로 압축된 tar 아카이브 (-c 생성, -z gzip, -f 파일 이름) 를 생성합니다.


네트워크 문제를 해결 중입니다. 로컬 머신에서 특정 포트 (예: 8080) 가 열려 있고 수신 대기 중인지, 그리고 어떤 프로세스가 사용하고 있는지 확인하는 방법은 무엇인가요?

답변:

netstat -tulnp | grep :8080 또는 lsof -i :8080을 사용합니다. netstat은 네트워크 연결을 보여주고, -t는 TCP, -u는 UDP, -l은 수신 대기 중, -n은 숫자, -p는 프로세스 ID 입니다. lsof는 네트워크 소켓을 포함한 열린 파일을 나열합니다.


URL (http://example.com/file.zip) 에서 파일을 다운로드하여 현재 디렉토리에 downloaded_file.zip으로 저장해야 합니다. 명령줄 도구를 사용하여 어떻게 할 수 있나요?

답변:

wget 또는 curl을 사용합니다. wget 사용 시: wget -O downloaded_file.zip http://example.com/file.zip. curl 사용 시: curl -o downloaded_file.zip http://example.com/file.zip. 두 도구 모두 HTTP/HTTPS 다운로드에 일반적입니다.


많은 파일이 있는 디렉토리가 있는데, .txt로 끝나는 모든 파일의 이름을 .log로 변경해야 합니다. 어떻게 달성할 수 있나요?

답변:

for 루프와 mv를 사용합니다. for f in *.txt; do mv "$f" "${f%.txt}.log"; done. "${f%.txt}.log" 구문은 .txt 접미사를 제거하고 .log를 추가합니다.


/var 디렉토리에서 가장 큰 파일 5 개를 찾고, /var/cache/var/log와 같은 하위 디렉토리는 제외해야 합니다.

답변:

dusort를 사용합니다. du -ah --exclude=/var/cache --exclude=/var/log /var | sort -rh | head -n 5. du -ah는 사람이 읽기 쉬운 형식으로 크기를 나열하고, sort -rh는 역순으로 숫자를 정렬하며, head -n 5는 상위 5 개를 가져옵니다.


스크립트가 매일 오전 3 시에 실행되어야 합니다. 이 작업을 어떻게 예약할 수 있나요?

답변:

cron을 사용합니다. crontab 에 항목을 추가합니다: 0 3 * * * /path/to/your/script.sh. 이는 매월, 매일, 매일의 3 시 0 분에 스크립트를 실행함을 의미합니다.


역할별 질문 (개발자, 관리자, DevOps)

개발자: 명확한 오류 메시지 없이 간헐적으로 실패하는 쉘 스크립트를 어떻게 디버깅하시겠습니까?

답변:

스크립트 시작 부분에 set -x를 추가하여 명령과 해당 인수가 실행될 때 표시되는 추적을 활성화하는 것으로 시작하겠습니다. 더 집중적인 디버깅을 위해 중요한 지점에서 변수 값을 출력하는 echo 문을 사용할 것입니다. stderr 를 파일로 리디렉션하는 것 (2> error.log) 도 파악하기 어려운 오류를 포착하는 데 도움이 될 수 있습니다.


개발자: 명령 치환에 대해 $()와 ``(백틱) 의 차이점을 설명해주세요.

답변:

$()와 ``(백틱) 모두 명령 치환을 수행하여 명령을 실행하고 그 출력으로 대체합니다. 그러나 $()는 복잡한 이스케이프 없이 중첩을 허용하고 가독성이 더 좋기 때문에 일반적으로 선호됩니다. 백틱은 중첩된 백틱을 이스케이프해야 하므로 관리하기가 더 어렵습니다.


개발자: 주어진 디렉토리와 그 하위 디렉토리에서 10MB 보다 큰 모든 파일을 찾은 다음, 크기별로 내림차순으로 나열하는 쉘 스크립트를 작성해주세요.

답변:

find /path/to/dir -type f -size +10M -print0 | xargs -0 du -h | sort -rh

이 명령어는 find를 사용하여 파일을 찾고, xargs를 사용하여 크기 보고를 위해 du로 전달하며, sort -rh를 사용하여 사람이 읽기 쉬운 크기별로 역순으로 정렬합니다.


관리자: Linux 서버의 디스크 공간 사용량을 어떻게 모니터링하고 90% 를 초과하면 알림을 설정하시겠습니까?

답변:

df -h를 사용하여 디스크 공간을 확인할 것입니다. 알림을 자동화하기 위해 df 출력을 파싱하고 중요한 파티션의 백분율을 확인한 다음, 임계값을 초과하면 mail 또는 메시징 API(예: Slack 웹훅) 를 사용하여 알림을 보내는 스크립트를 작성할 것입니다. 이 스크립트는 cron 을 통해 예약될 것입니다.


관리자: SSH 를 사용하여 특정 디렉토리의 일일 백업을 원격 서버로 자동화하는 단계를 설명해주세요.

답변:

먼저 소스 서버와 대상 서버 간에 SSH 키 기반 인증이 설정되어 있는지 확인하여 암호 프롬프트를 방지합니다. 그런 다음 쉘 스크립트 내에서 rsync -avz /source/dir/ user@remote:/destination/dir/를 사용합니다. 이 스크립트를 cron 작업을 사용하여 매일 실행하도록 예약하고 적절한 로깅 및 오류 처리를 보장합니다.


관리자: /etc/fstab 파일의 목적은 무엇이며, 이 파일과 관련하여 발생할 수 있는 일반적인 문제는 무엇인가요?

답변:

/etc/fstab은 부팅 시 마운트될 정적 파일 시스템을 정의합니다. 일반적인 문제로는 잘못된 장치 경로, 잘못된 파일 시스템 유형 또는 잘못된 마운트 옵션이 있으며, 이는 부팅 실패 또는 파티션이 마운트되지 않는 결과를 초래할 수 있습니다. nofail을 사용하면 중요하지 않은 마운트에 대한 부팅 문제를 방지할 수 있습니다.


DevOps: 인프라 프로비저닝을 위한 쉘 스크립트에서 어떻게 멱등성 (idempotency) 을 보장하시겠습니까?

답변:

멱등성은 스크립트를 여러 번 실행해도 한 번 실행한 것과 동일한 결과를 얻는 것을 의미합니다. 이를 위해 리소스를 생성하기 전에 해당 리소스의 존재 여부를 확인합니다 (예: if [ ! -f /path/to/file ]; then ... fi). 패키지 설치의 경우 멱등성을 처리하는 패키지 관리자 (예: apt install -y package는 존재하지 않는 경우에만 설치) 를 사용합니다. Ansible 또는 Puppet 과 같은 구성 관리 도구는 본질적으로 멱등성을 제공합니다.


DevOps: CI/CD 파이프라인에서 쉘 스크립트를 사용하여 애플리케이션을 배포하는 방법을 설명해주세요.

답변:

CI/CD 파이프라인에서 쉘 스크립트는 일반적으로 아티팩트 가져오기, 기존 서비스 중지, 새 코드 배포 (예: 파일 복사, 아카이브 압축 해제), 데이터베이스 마이그레이션 실행, 서비스 시작과 같은 작업을 처리합니다. 오류 처리 및 로깅을 포함하며, 종종 systemctl 또는 docker 명령과 상호 작용합니다. 환경 변수는 구성을 위해 사용될 것입니다.


DevOps: 팀 환경에서 강력하고 유지보수 가능한 쉘 스크립트를 작성하기 위한 몇 가지 모범 사례는 무엇인가요?

답변:

모범 사례에는 오류 처리를 위한 set -euo pipefail 사용, 주석 추가, 코드 모듈화를 위한 함수 사용, 일관된 명명 규칙, 입력 유효성 검사 및 명확한 사용 지침 제공이 포함됩니다. 버전 관리, 린팅 도구 (ShellCheck 등) 및 철저한 테스트도 팀 협업 및 유지보수성에 매우 중요합니다.


DevOps: CI/CD 컨텍스트에서 쉘 스크립트의 비밀 (예: API 키, 비밀번호) 을 어떻게 처리하시겠습니까?

답변:

비밀은 절대 하드코딩해서는 안 됩니다. CI/CD에서는 CI/CD 플랫폼에서 제공하는 환경 변수 (예: Jenkins 자격 증명, GitLab CI/CD 변수) 를 사용할 것입니다. 더 민감하거나 복잡한 시나리오의 경우 HashiCorp Vault 또는 AWS Secrets Manager 와 같은 비밀 관리 시스템과 통합하여 스크립트나 리포지토리에 저장하는 대신 런타임에 비밀을 검색할 것입니다.


실용적인 스크립팅 및 실습 과제

디렉토리 경로를 인수로 받아 해당 디렉토리 내의 일반 파일 및 하위 디렉토리 수를 세는 쉘 스크립트를 작성하세요. 디렉토리가 존재하지 않는 경우를 처리하세요.

답변:

#!/bin/bash
DIR="$1"
if [ ! -d "$DIR" ]; then
  echo "Error: Directory '$DIR' not found."
  exit 1
fi
files=$(find "$DIR" -maxdepth 1 -type f | wc -l)
dirs=$(find "$DIR" -maxdepth 1 -type d | wc -l)
## Subtract 1 from dirs for the directory itself
echo "Files: $files, Directories: $((dirs - 1))"

현재 디렉토리 및 하위 디렉토리에서 10MB 보다 큰 모든 파일을 찾은 다음, 크기별로 정렬하여 나열하는 방법은 무엇인가요?

답변:

find . -type f -size +10M -print0 | xargs -0 du -h | sort -rh를 사용합니다. find는 파일을 찾고, -print0xargs -0은 특수 문자를 처리하며, du -h는 사람이 읽기 쉬운 크기를 가져오고, sort -rh는 사람이 읽기 쉬운 크기별로 역순으로 정렬합니다.


현재 디렉토리의 모든 .txt 파일에서 'foo'의 모든 발생을 'bar'로 바꾸는 한 줄 명령어를 작성하세요.

답변:

find . -maxdepth 1 -type f -name "*.txt" -exec sed -i 's/foo/bar/g' {} \;

이것은 find를 사용하여 .txt 파일을 찾고 sed -i를 사용하여 제자리에서 바꾸는 것입니다. 대안으로 grep -lR foo *.txt | xargs sed -i 's/foo/bar/g'를 사용할 수 있습니다.


쉘 스크립트에서 $$$!의 차이점을 설명해주세요.

답변:

$$는 현재 쉘의 프로세스 ID(PID) 로 확장됩니다. $!는 가장 최근에 실행된 백그라운드 (비동기) 명령의 PID 로 확장됩니다. 고유한 임시 파일을 생성하거나 백그라운드 프로세스를 관리하는 데 유용합니다.


쉘 스크립트에서 명령줄 인수를 파싱하는 방법, 특히 --file <path> 또는 -v와 같은 명명된 인수를 파싱하는 방법은 무엇인가요?

답변:

짧은 옵션 (-v) 의 경우 getopts 또는 while getopts 루프를 사용합니다. 긴 옵션 (--file) 의 경우 while true; do case "$1" in ... esac; shift; done 루프와 case 문을 사용하는 것이 일반적이며, 종종 shift와 함께 사용하여 인수를 소비합니다.


로그 파일 (/var/log/syslog 등) 을 모니터링하고 새 줄이 추가될 때마다 tail -f와 유사하게 출력하는 스크립트를 작성하세요.

답변:

#!/bin/bash
tail -f /var/log/syslog

이것은 이 목적을 위해 설계된 tail -f 명령을 직접 활용합니다. 더 수동적인 접근 방식의 경우 inotifywait 또는 wc -lsed를 사용하는 루프를 사용할 수 있습니다.


어떤 명령이든 실패하면 쉘 스크립트가 즉시 종료되도록 하는 방법은 무엇인가요?

답변:

스크립트 시작 부분에 set -e를 추가합니다. 이 옵션은 명령이 0 이 아닌 상태로 종료되면 쉘이 즉시 종료되도록 합니다. 강력한 스크립트 실행에 매우 중요합니다.


Name,Age,City 열이 있는 CSV 파일 data.csv가 있습니다. 표준 쉘 도구를 사용하여 NameCity 열만 추출하는 방법은 무엇인가요?

답변:

cut -d',' -f1,3 data.csv

이것은 쉼표 구분 기호 (-d',') 와 함께 cut을 사용하여 첫 번째와 세 번째 필드 (-f1,3) 를 선택합니다. 대안으로 awk -F',' '{print $1 "," $3}' data.csv를 사용하여 동일한 작업을 수행할 수 있습니다.


두 개의 숫자를 인수로 받아 합계를 반환하는 쉘 스크립트 함수를 작성하세요.

답변:

#!/bin/bash
sum_numbers() {
  echo $(($1 + $2))
}
result=$(sum_numbers 10 5)
echo "Sum: $result"

함수는 function_name() { ... }으로 정의됩니다. 산술 확장 $((...))은 계산에 사용됩니다. 결과는 일반적으로 출력되고 명령 치환으로 캡처됩니다.


스크립트를 매일 오전 3 시에 실행하도록 예약하는 방법은 무엇인가요?

답변:

cron을 사용합니다. crontab 파일 (crontab -e) 에 0 3 * * * /path/to/your_script.sh와 같은 항목을 추가합니다. 필드는 각각 분, 시, 월의 일, 월, 주의 일을 나타냅니다.


쉘 스크립트 문제 해결 및 디버깅

쉘 모범 사례 및 성능 최적화

대용량 파일 또는 많은 반복을 처리할 때 쉘 스크립트의 성능을 최적화하는 방법은 무엇인가요?

답변:

불필요한 포크 (fork) 를 피하세요 (예: 루프 내에서 grep 사용). 가능한 경우 내장 쉘 기능 (예: sed 대신 매개변수 확장) 을 사용하세요. 데이터를 청크 (chunk) 로 처리하거나 효율적인 줄별 처리를 위해 awk를 사용하세요.


명령 치환 (command substitution) 에 대해 $(command)`command`의 차이점을 설명하고, 모범 사례로 선호되는 것은 무엇인가요?

답변:

$(command)는 현대적이고 선호되는 구문입니다. 중첩을 더 쉽게 처리하고 백틱 (`command`) 에서 발생할 수 있는 백슬래시 및 따옴표 문제를 피합니다. $(command)는 일반적으로 더 읽기 쉽고 강력합니다.


쉘 스크립트에서 set -eset -u의 목적은 무엇이며, 왜 좋은 습관으로 간주되나요?

답변:

set -e (errexit) 는 명령이 0 이 아닌 상태로 종료되면 스크립트가 즉시 종료되도록 합니다. set -u (nounset) 는 설정되지 않은 변수를 오류로 취급하고 종료합니다. 둘 다 오류를 조기에 감지하고 예기치 않은 동작을 방지하여 스크립트의 견고성을 향상시킵니다.


쉘 스크립트에서 'globbing' 또는 경로명 확장 (pathname expansion) 을 방지하는 방법은 무엇인가요?

답변:

globbing 을 방지하려면 문자열을 큰따옴표로 묶으세요. 예를 들어, ls "*.txt"*.txt를 리터럴 문자열로 처리하는 반면, ls *.txt는 현재 디렉토리의 모든 .txt 파일로 확장됩니다.


Bash 에서 조건식에 [ ... ] 대신 [[ ... ]]를 사용해야 하는 경우는 언제인가요?

답변:

[[ ... ]]는 POSIX 호환 [ ... ] 명령보다 더 많은 기능을 제공하는 Bash 특정 키워드입니다. 패턴 매칭 (=~), 논리 연산자 (&&, ||) 를 지원하며 단어 분리 및 경로명 확장을 피하여 더 안전하고 강력합니다.


for 루프보다 xargs를 사용하는 것이 더 효율적인 시나리오를 설명하세요.

답변:

xargs는 많은 항목 목록을 명령의 인수로 처리할 때 더 효율적입니다. 여러 인수로 명령줄을 구축하여 대상 명령이 호출되는 횟수를 줄입니다. 이는 일반적으로 각 항목에 대해 명령을 한 번 호출하는 for 루프와 다릅니다.


stderr/dev/null로 리디렉션하는 것 (2>/dev/null 등) 의 중요성은 무엇인가요?

답변:

stderr/dev/null로 리디렉션하면 오류 메시지가 삭제되어 콘솔에 표시되거나 출력이 오염되는 것을 방지합니다. 이는 예상되는 오류를 억제하거나 stdout만 관심 있는 경우에 유용합니다.


쉘 스크립트를 다른 Unix 계열 시스템 간에 더 이식성 있게 만드는 방법은 무엇인가요?

답변:

가능한 경우 POSIX 호환 명령 및 기능을 사용하세요. 엄격한 이식성이 필요한 경우 [[ ... ]] 또는 프로세스 치환과 같은 Bash 특정 확장을 피하세요. #!/bin/sh와 같은 셔뱅 (shebang) 을 사용하여 인터프리터를 명시적으로 지정하세요.


쉘 스크립트에서 ls 출력을 파싱하는 것이 일반적으로 좋지 않은 습관인 이유는 무엇인가요?

답변:

ls 출력을 파싱하는 것은 파일 이름에 공백, 줄 바꿈 또는 특수 문자가 포함될 수 있어 awk 또는 for 루프와 같은 도구로 처리할 때 스크립트 논리를 중단시킬 수 있기 때문에 문제가 됩니다. 안전한 파일 이름 처리를 위해 find -print0 | xargs -0을 사용하세요.


쉘 스크립팅에서 trap의 목적은 무엇이며, 간단한 예를 들어 설명하세요.

답변:

trap을 사용하면 쉘이 신호 (예: EXIT, INT, TERM) 를 받을 때 명령을 실행할 수 있습니다. 정리 작업에 매우 중요합니다. 예: trap 'rm -f /tmp/mytempfile' EXIT는 스크립트가 종료될 때 임시 파일이 제거되도록 합니다.


쉘을 이용한 버전 관리 및 협업

일상적인 개발 작업에서 명령줄을 통해 Git 을 어떻게 사용하나요?

답변:

주로 git status, git add, git commit -m "message", git pull, git push를 사용합니다. 브랜칭을 위해서는 git checkout -b branch_namegit merge 또는 git rebase를 사용합니다.


git pullgit fetch의 차이점을 설명해주세요.

답변:

git fetch는 원격 저장소에서 새 데이터를 다운로드하지만 작업 파일에는 통합하지 않습니다. git pull은 본질적으로 git fetch 다음에 git merge(또는 구성에 따라 git rebase) 를 수행하여 변경 사항을 현재 브랜치에 통합합니다.


원격 저장소에 이미 푸시된 특정 커밋을 되돌리려면 어떻게 해야 하나요?

답변:

git revert <commit_hash>를 사용합니다. 이는 지정된 커밋의 변경 사항을 취소하는 새 커밋을 생성하여 프로젝트 기록을 보존합니다. 공유 브랜치의 경우 git reset --hard보다 안전합니다.


git merge 대신 git rebase를 사용해야 하는 시나리오를 설명해주세요.

답변:

git rebase는 특히 main으로 병합하기 전 기능 브랜치에서 깔끔하고 선형적인 프로젝트 기록을 유지하기 위해 사용합니다. 한 브랜치의 커밋을 다른 브랜치에 다시 적용하여 병합 커밋을 피하고 기록을 더 쉽게 읽을 수 있도록 합니다.


명령줄을 사용하여 병합 충돌을 해결하는 방법은 무엇인가요?

답변:

병합 충돌 후 git status는 충돌한 파일을 보여줍니다. 이러한 파일을 수동으로 편집하여 충돌을 해결한 다음 git add <conflicted_file>을 사용하여 해결되었음을 표시합니다. 마지막으로 git commit으로 병합을 완료합니다.


git stash는 무엇이며 언제 사용하나요?

답변:

git stash는 커밋할 준비가 되지 않은 변경 사항을 임시로 저장하여 브랜치를 전환하거나 다른 작업을 수행할 수 있도록 합니다. 불완전한 작업을 커밋하지 않고 빠르게 컨텍스트를 전환해야 할 때 유용합니다.


특정 파일의 커밋 기록을 어떻게 볼 수 있나요?

답변:

git log -- <file_path>를 사용합니다. 이 명령은 지정된 파일에 영향을 미친 모든 커밋 (커밋 해시, 작성자, 날짜 및 커밋 메시지 포함) 을 보여줍니다.


실수로 민감한 정보를 커밋했습니다. Git 기록에서 이를 제거하려면 어떻게 해야 하나요?

답변:

최근에 푸시되지 않은 커밋의 경우 git reset HEAD~1을 사용한 다음 커밋을 수정하는 것이 한 가지 방법입니다. 푸시된 커밋이나 더 깊은 기록의 경우 git filter-branch 또는 BFG Repo-Cleaner를 사용하여 기록을 다시 작성하지만, 이는 파괴적이며 강제 푸시가 필요합니다.


.gitignore 파일의 목적을 설명해주세요.

답변:

.gitignore 파일은 Git 이 무시해야 하는 의도적으로 추적되지 않은 파일을 지정합니다. 이를 통해 임시 파일, 빌드 아티팩트 또는 민감한 구성 파일이 저장소에 실수로 커밋되는 것을 방지합니다.


Git 에서 새 브랜치를 생성하고 전환하는 방법은 무엇인가요?

답변:

새 브랜치를 생성하고 전환하려면 git checkout -b new-branch-name을 사용합니다. 이 명령은 git branch new-branch-name 다음에 git checkout new-branch-name을 수행하는 바로 가기입니다.


쉘 스크립팅의 보안 고려 사항

신뢰할 수 없는 소스에서 다운로드한 쉘 스크립트를 실행하는 것이 위험한 이유는 무엇인가요?

답변:

신뢰할 수 없는 스크립트에는 파일을 삭제하거나, 악성코드를 설치하거나, 민감한 데이터를 훔치거나, 백도어를 생성할 수 있는 악성 코드가 포함될 수 있습니다. 스크립트는 실행하는 사용자의 권한으로 실행되므로 상당한 보안 위험을 초래합니다.


쉘 스크립트에서 명령 주입 (command injection) 취약점을 방지하는 방법은 무엇인가요?

답변:

사용자 입력이 포함된 변수는 항상 따옴표로 묶으세요. 특히 명령에 사용될 때 더욱 그렇습니다. 오류 및 설정되지 않은 변수를 잡기 위해 set -eset -u를 사용하세요. 신뢰할 수 없는 입력과 함께 eval을 피하세요. 일반적인 명령보다 특정 명령을 선호하고 입력을 철저히 검증하세요.


보안을 위해 쉘 스크립팅에서 입력 유효성 검사 (input validation) 의 중요성을 설명해주세요.

답변:

입력 유효성 검사는 스크립트에 제공된 데이터가 예상되는 형식과 값에 부합하도록 보장하여 악의적인 입력이 처리되는 것을 방지합니다. 이는 잘못되거나 위험한 문자를 거부함으로써 명령 주입, 경로 탐색 (path traversal) 및 버퍼 오버플로와 같은 위험을 완화합니다.


쉘 스크립트에서 eval을 사용할 때의 위험은 무엇이며, 언제 허용될 수 있나요?

답변:

eval은 인수를 쉘 명령으로 실행하므로 신뢰할 수 없는 입력과 함께 사용될 경우 명령 주입에 매우 취약합니다. 일반적으로 입력이 스크립트 자체에서 완전히 제어되고 신뢰할 수 있는 경우 또는 동적으로 간단하고 안전한 명령을 구성할 때만 허용됩니다.


쉘 스크립트에서 비밀번호나 API 키와 같은 민감한 정보를 안전하게 처리하는 방법은 무엇인가요?

답변:

스크립트에 민감한 데이터를 직접 하드코딩하지 마세요. 대신 환경 변수 (주의해서 사용), 제한된 권한이 있는 보안 구성 파일 또는 HashiCorp Vault 나 AWS Secrets Manager 와 같은 전용 비밀 관리 도구를 사용하세요. 버전 관리 시스템에 저장하지 마세요.


쉘 스크립트 및 해당 출력 파일에 적절한 파일 권한을 설정하는 것이 중요한 이유는 무엇인가요?

답변:

잘못된 파일 권한은 권한이 없는 사용자가 스크립트나 해당 출력을 읽거나 수정하거나 실행할 수 있도록 허용할 수 있습니다. 스크립트는 일반적으로 소유자만 실행할 수 있어야 하며, 민감한 출력 파일은 데이터 유출이나 변조를 방지하기 위해 제한적인 읽기/쓰기 권한을 가져야 합니다.


보안을 위해 쉘 스크립트에서 set -u (또는 set -o nounset) 의 목적은 무엇인가요?

답변:

set -u는 설정되지 않은 변수를 사용하려고 하면 스크립트가 즉시 종료되도록 합니다. 이는 초기화되지 않은 변수가 빈 문자열이나 기본값으로 해석되어 의도하지 않은 명령 실행이나 파일 작업으로 이어질 수 있는 예기치 않은 동작이나 보안 취약점을 방지합니다.


쉘 스크립트 실행 맥락에서 '최소 권한 (least privilege)'의 개념을 설명해주세요.

답변:

최소 권한 원칙은 스크립트가 의도된 기능을 수행하는 데 필요한 최소한의 권한으로 실행되어야 함을 규정합니다. 이는 스크립트가 손상되었을 경우 잠재적인 피해를 제한합니다. 왜냐하면 필요하지 않은 시스템이나 데이터에 대한 상승된 접근 권한을 갖지 않기 때문입니다.


경로 조작 (path manipulation) 이 쉘 스크립트에서 보안 취약점으로 이어질 수 있는 방법은 무엇인가요?

답변:

PATH 환경 변수가 신중하게 제어되지 않으면 악의적인 사용자가 유사한 이름의 실행 파일 (예: ls 또는 rm) 이 포함된 자체 디렉토리를 삽입할 수 있습니다. 스크립트가 해당 명령을 호출할 때 합법적인 버전 대신 악의적인 버전을 실행하여 의도하지 않은 작업을 수행할 수 있습니다.


안전한 쉘 스크립트를 작성하기 위한 몇 가지 모범 사례는 무엇인가요?

답변:

모든 사용자 입력을 검증하고, 변수를 따옴표로 묶고, set -euo pipefail을 사용하고, 신뢰할 수 없는 데이터와 함께 eval을 피하고, 제한적인 파일 권한을 설정하고, 명령에 절대 경로를 사용하고, 최소 권한 원칙을 따르세요. 스크립트를 정기적으로 감사하여 취약점을 확인하고 최신 상태로 유지하세요.


요약

Shell 의 엄격한 면접 과정에서 성공하기 위해서는 철저한 준비가 무엇보다 중요합니다. 일반적인 질문을 성실히 검토하고, Shell 의 가치를 이해하며, 답변을 연습함으로써 자신의 역량과 역할에 대한 적합성을 보여줄 가능성을 크게 높일 수 있습니다. 이 문서는 잠재적인 질문을 예상하고 설득력 있는 답변을 구성하는 데 도움이 되는 귀중한 자료 역할을 합니다.

면접으로 여정이 끝나는 것이 아님을 기억하십시오. 에너지 산업은 역동적이며 지속적인 학습은 전문적인 성장에 핵심입니다. 끊임없이 변화하는 환경에서 귀중한 자산으로 남기 위해 지식과 기술을 확장할 모든 기회를 받아들이십시오. 준비와 평생 학습에 대한 헌신은 의심할 여지 없이 만족스러운 경력의 길을 열어줄 것입니다.