Bash 5.1 기능 및 개선 사항
2020년 12월에 출시된 Bash 5.1은 현대적인 셸 스크립트 작성을 위한 여러 주목할 만한 기능과 개선 사항을 도입했습니다.
새로운 셸 변수
EPOCHSECONDS 및 EPOCHREALTIME
현재 시간에 접근하기 위한 두 가지 새로운 특수 변수:
# 현재 유닉스 타임스탬프(초 단위) 가져오기
echo "현재 타임스탬프: ${EPOCHSECONDS}"
# 마이크로초 정밀도의 현재 유닉스 타임스탬프 가져오기
echo "고정밀 타임스탬프: ${EPOCHREALTIME}"
# 실용 예제: 간단한 벤치마킹
start="${EPOCHREALTIME}"
# ... 일부 작업 ...
sleep 0.5
end="${EPOCHREALTIME}"
duration=$(awk "BEGIN {print ${end} - ${start}}")
echo "작업에 ${duration}초 소요됨"
# 예제: 정밀한 타임스탬프로 로그 남기기
log_message() {
printf '[%s.%06d] %s\n' \
"$(date -d "@${EPOCHSECONDS}" '+%Y-%m-%d %H:%M:%S')" \
"${EPOCHREALTIME#*.}" \
"$*"
}
log_message "프로세스 시작"
사용 사례:
- 정밀한 성능 측정
- 로깅을 위한 고해상도 타임스탬프
- 외부
date명령 호출 회피 - 스크립트에서 마이크로초 정밀도 타이밍
SRANDOM 변수
암호학적으로 강력한 난수:
# 보안 난수 생성 (가능한 경우)
if [[ -n "${SRANDOM}" ]]; then
secure_random="${SRANDOM}"
echo "보안 난수: ${secure_random}"
else
echo "SRANDOM을 사용할 수 없음 (getrandom/getentropy 필요)"
fi
# 실용 예제: 보안 난수 이름으로 임시 파일 생성
temp_file="/tmp/secure_${SRANDOM}_${EPOCHSECONDS}.tmp"
참고: SRANDOM은 시스템이 getrandom() 또는 getentropy() 시스템 콜을 지원해야 합니다.
개선된 리다이렉션 문법
{varname} 리다이렉션
파일 기술자를 변수에 할당하여 파일 핸들 관리 개선:
# 파일 기술자를 열고 변수에 저장
exec {fd}< input.txt
while IFS= read -r -u "${fd}" line; do
echo "읽음: ${line}"
done
exec {fd}<&- # 파일 기술자 닫기
# 실용 예제: 여러 파일 핸들
exec {input_fd}< data.txt
exec {output_fd}> results.txt
exec {error_fd}> errors.txt
process_data() {
while IFS= read -r -u "${input_fd}" line; do
if validate_line "${line}"; then
echo "처리됨: ${line}" >&"${output_fd}"
else
echo "오류: ${line}" >&"${error_fd}"
fi
done
}
process_data
exec {input_fd}<&-
exec {output_fd}>&-
exec {error_fd}>&-
이점:
- 매직 넘버 대신 명명된 파일 기술자
- 자동 FD 할당으로 충돌 방지
- 더 읽기 쉽고 유지보수하기 쉬운 코드
- 열린 파일 핸들 추적 용이
배열 향상
향상된 연관 배열 처리
복잡한 배열 연산에 대한 더 나은 지원:
# typeset으로 연관 배열 선언
declare -A config=(
[host]="localhost"
[port]="8080"
[debug]="true"
)
# 향상된 배열 확장
for key in "${!config[@]}"; do
printf '%s=%s\n' "${key}" "${config[${key}]}"
done
# 실용 예제: 설정 파서
parse_config() {
declare -gA app_config
local line key value
while IFS='=' read -r key value; do
[[ "${key}" =~ ^[[:space:]]*# ]] && continue # 주석 건너뛰기
[[ -z "${key}" ]] && continue # 빈 줄 건너뛰기
# 공백 제거
key="${key#"${key%%[![:space:]]*}"}"
key="${key%"${key##*[![:space:]]}"}"
value="${value#"${value%%[![:space:]]*}"}"
value="${value%"${value##*[![:space:]]}"}"
app_config["${key}"]="${value}"
done < config.ini
}
다차원 배열 지원
중첩 배열 구조의 향상된 처리.
Readline 8.1 통합
향상된 텍스트 편집 및 명령줄 상호작용:
키 바인딩 및 히스토리
# ~/.inputrc에서 readline 설정
# 대소문자 구분 없는 완성 활성화
set completion-ignore-case on
# 완성 시 visible stats 활성화
set visible-stats on
# 모든 완성을 즉시 표시
set show-all-if-ambiguous on
# 완성 일치에 색상 사용
set colored-completion-prefix on
향상된 히스토리 검색
# 스크립트 또는 .bashrc에서
# Ctrl+R을 역방향 증분 검색에 바인딩 (기본값이지만 5.1에서 향상됨)
bind '"\C-r": reverse-search-history'
# Ctrl+S를 순방향 증분 검색에 바인딩
bind '"\C-s": forward-search-history'
# 향상된 히스토리 처리
shopt -s histappend # 히스토리에 추가
shopt -s cmdhist # 여러 줄 명령을 하나의 항목으로
HISTCONTROL=ignoreboth # 중복 및 선행 공백 무시
HISTSIZE=10000
HISTFILESIZE=20000
신호 처리 개선
서브셸 및 프로세스 치환에서 더 나은 신호 전파:
# 서브셸에서 향상된 트랩 처리
cleanup() {
echo "정리 중..." >&2
rm -f "${temp_file}"
exit 130 # 128 + SIGINT
}
trap cleanup SIGINT SIGTERM
temp_file=$(mktemp)
# 파이프라인을 통해 신호가 올바르게 전파됨
long_running_task | process_output &
pid=$!
# 적절한 신호 처리를 통해 백그라운드 작업 대기
wait "${pid}" 2>/dev/null
exit_code=$?
if [[ ${exit_code} -gt 128 ]]; then
signal=$((exit_code - 128))
echo "프로세스가 신호 ${signal}에 의해 종료됨" >&2
fi
버그 수정 및 엣지 케이스
서브셸 처리
서브셸 생성 시 동작 개선:
# 더 안정적인 서브셸 변수 상속
outer_var="parent"
(
# 서브셸이 이제 부모 변수를 더 안정적으로 상속
echo "서브셸에서: ${outer_var}"
inner_var="child"
)
# outer_var는 여전히 접근 가능, inner_var는 불가능
echo "서브셸 이후: ${outer_var}"
패턴 매칭 엣지 케이스
글로브 패턴 매칭의 엣지 케이스 수정:
# 특수 문자를 포함한 더 안정적인 글로브 매칭
shopt -s nullglob # 일치하는 글로브가 없을 때 빈 확장
shopt -s extglob # 확장 패턴 매칭
# 예제: 일치하는 파일이 없을 때 우아하게 처리
files=(*.txt)
if [[ ${#files[@]} -eq 0 ]]; then
echo ".txt 파일을 찾을 수 없음"
else
printf '찾음: %s\n' "${files[@]}"
fi
성능 개선
- 루프 내에서 더 빠른 변수 확장
- 최적화된 배열 연산
- 큰 배열에 대한 메모리 사용량 감소
- 패턴 매칭의 효율성 향상
호환성 참고 사항
Bash 5.0에서 업그레이드
대부분의 스크립트는 호환되지만, 다음을 참고하세요:
EPOCHSECONDS와EPOCHREALTIME은 새로운 변수이므로 이전 버전을 대상으로 할 경우 존재 여부를 확인하세요SRANDOM은 모든 시스템에서 사용 가능하지 않을 수 있습니다- 확장 동작의 일부 흔하지 않은 엣지 케이스가 수정되었습니다
버전 확인
# Bash 5.1 기능을 사용하기 전에 Bash 버전 확인
if [[ "${BASH_VERSINFO[0]}" -ge 5 ]] && [[ "${BASH_VERSINFO[1]}" -ge 1 ]]; then
# Bash 5.1 기능을 안전하게 사용 가능
timestamp="${EPOCHSECONDS}"
else
# 이전 버전을 위한 대체 방법
timestamp=$(date +%s)
fi
참고 자료
- Bash NEWS 파일 - 공식 릴리스 노트
- GNU Bash 5.1 릴리스 - 소스 배포판
- Bash 매뉴얼 페이지:
man bash(버전별 기능 섹션)
추가 자료
더 광범위한 Bash 개발 패턴 및 모범 사례는 다음을 참조하세요:
- ../bash-development/SKILL.md - 핵심 Bash 개발 패턴
- ../bash-portability/SKILL.md - 크로스 버전 호환성