현재 나는 더 큰 Bash 스크립트 (내 오픈 소스 프로젝트)를 개발 중이며 엉망이되기 시작합니다. 논리를 함수로 나누고 소수의 전역 변수 만 선언 할 수있는 로컬 변수를 사용했습니다. 여전히 유지 관리가 매우 어려워지고 있습니다.
스크립트를 여러 스크립트로 나누고 주 스크립트에서 다른 언어로 가져 오는 것과 비슷하게 생각했습니다.
그러나 이것이 가능한 접근법인지 궁금합니다. 첫째, 여러 스크립트를 소싱하면 스크립트 실행 시간이 크게 느려질 수 있으며, 두 번째로 배포가 더 어려워집니다.
그렇다면 이것은 좋은 접근 방법이며 다른 (오픈 소스) 프로젝트도 같은 방식입니까?
답변
예, 일반적인 관행입니다. 예를 들어 Unix 초기에는 부팅 단계를 통해 시스템을 다중 사용자 작업으로 안내하는 셸 코드가 단일 파일이었습니다 /etc/rc
. 오늘날 부트 프로세스는 많은 쉘 스크립트에 의해 제어되며 기능별로 분류되어 있으며 공통 기능과 변수가 중앙 위치에서 필요에 따라 제공됩니다. Linux 배포판, Mac, BSD는 모두이 접근 방식을 다양한 정도로 채택했습니다.
답변
이 시점에서 쉘이 작업에 적합한 도구입니까? 코드가 커지는 문제에 부딪힌 개발자는 다시 쓰기를 고려해야한다고 생각할 수 있지만 대신 파이썬이나 루비 또는 펄과 같이 응용 프로그램을 확장하려는 규모에 더 적합한 조각으로 조각을 분리하는 것을 고려할 수 있습니다 ?
셸은 유틸리티 언어이며 스크립트 언어이므로 이러한 크기로 확장하기가 어렵습니다.
답변
유지 관리가 더 쉬워지면 둘 다 가질 수 있습니다. 논리적 부분으로 분할하여 쉽게 관리 할 수 있도록 한 다음 Makefile을 작성 (예를 들어) 배포 할 수 있도록 다시 정리하십시오. 빠른 스크립트를 작성하여 포함 파일에서 출력 파일로 대신 함수를 복사 할 수 있습니다. source
라인이 아니면 그냥 이런 사소한 일을 (같은 당신이 다시 tabify해야합니다 make
탭 필요) :
all: myscript
myscript: includes/* body/*
cat $^ > "$@" || (rm -f "$@"; exit 1)
그런 다음 “소스”버전 (편집에 사용)과 “이진”버전 (간편한 설치에 사용)이 있습니다.
답변
설명하는대로 스크립트가 손상 될 수 있습니다. ‘좋은 접근 방식’은 큰 스크립트를 구획화하고 그 일부가 별도의 프로세스로 실행될 수있는 위치를 파악하여 IPC 메커니즘을 통해 통신하는 것입니다.
그 외에도 쉘 스크립트의 경우 단일 파일로 패키지합니다. 당신이 말했듯이, 배포가 더 어려워집니다 : ‘라이브러리’스크립트가 어디에 있는지 알아야합니다-쉘 스크립트에는 좋은 표준이 없습니다-또는 경로를 올바르게 설정하기 위해 사용자에게 의존하십시오.
이 모든 것을 처리하는 설치 프로그램을 배포하여 파일을 추출하여 적절한 위치 export PROGRAMDIR=$HOME/lib/PROGRAM
에 놓고 ~ / .bashrc 파일 과 같은 것을 추가하도록 사용자에게 지시 할 수 있습니다 . 그러면 $PROGRAMDIR
설정되지 않았거나 원하는 파일이 포함되어 있지 않으면 주 프로그램이 실패 할 수 있습니다.
다른 스크립트를로드하는 오버 헤드에 대해서는별로 걱정하지 않습니다. 오버 헤드는 실제로 파일을 여는 것입니다. 텍스트 처리는 특히 함수 정의 인 경우 동일합니다.
답변
일반적인 관행이든 아니든 일련의 수출 이외의 것을 소싱하는 것은 좋은 생각이 아닙니다. 소싱하여 코드를 실행하는 것은 혼란스럽고 환경 및 기타 변수 설정으로 인해 소스 코드가 소싱 코드에 크게 의존하기 때문에 재사용이 제한됩니다.
응용 프로그램을 더 작은 자체 포함 스크립트로 분할 한 다음 일련의 명령으로 실행하는 것이 좋습니다. 대화식 쉘에서 각각의 자체 포함 스크립트를 실행하고 각 명령 호출간에 파일, 로그 등을 검사 할 수 있으므로 디버깅이 쉬워집니다. 하나의 큰 응용 프로그램 스크립트는 디버깅을 마친 후에 일련의 명령을 실행하는 간단한 제어 스크립트로 바뀝니다.
더 작고 독립적 인 스크립트 그룹이 설치하기 어려운 문제에 부딪칩니다.
답변
스크립트 소싱의 대안은 단순히 인수로 스크립트를 호출하는 것입니다. 대부분의 기능을 이미 셸 함수로 나눈 경우 이미이 작업을 수행 할 수있을 것입니다. 다음 Bash 스 니펫을 사용하면 스크립트에 선언 된 함수를 하위 명령으로 사용할 수 있습니다.
if [[ ${1:-} ]] && declare -F | cut -d' ' -f3 | fgrep -qx -- "${1:-}"
then "$@"
else main "$@" # Try the main function if args don't match a declaration.
fi
하지 말아야 할 이유 source
는 환경 및 옵션 오염을 피하기 위해서입니다.
답변
다음은 큰 bash 스크립트를 여러 파일로 분할 한 다음 하나의 결과 스크립트로 만드는 방법에 대한 예입니다. https://github.com/zinovyev/bash-project
나는 Makefile
이것을 목적으로 사용합니다 :
TARGET_FILE = "target.sh"
PRJ_SRC = "${PWD}/src/main.sh"
PRJ_LIB = $(shell ls -d ${PWD}/lib/*) # All files from ./lib
export PRJ_LIB
SHELL := /bin/env bash
all: define_main add_dependencies invoke_main
define_main:
echo -e "#!/usr/bin/env bash\n" > ${TARGET_FILE}
echo -e "function main() {\n" >> ${TARGET_FILE}
cat "${PRJ_SRC}" | sed -e 's/^/ /g' >> ${TARGET_FILE}
echo -e "\n}\n" >> ${TARGET_FILE}
invoke_main:
echo "main \$$@" >> ${TARGET_FILE}
add_dependencies:
for filename in $${PRJ_LIB[*]}; do cat $${filename} >> ${TARGET_FILE}; echo >> ${TARGET_FILE}; done