더 큰 스크립트를 여러 개의 스크립트로 분할하여 기본 스크립트에서 제공하는 것이 일반적입니까?


23

현재 나는 더 큰 Bash 스크립트 (내 오픈 소스 프로젝트)를 개발 중이며 엉망이되기 시작합니다. 논리를 함수로 나누고 소수의 전역 변수 만 선언 할 수있는 로컬 변수를 사용했습니다. 여전히 유지 관리가 매우 어려워지고 있습니다.

스크립트를 여러 스크립트로 나누고 주 스크립트에서 다른 언어로 가져 오는 것과 비슷하게 생각했습니다.

그러나 이것이 가능한 접근법인지 궁금합니다. 첫째, 여러 스크립트를 소싱하면 스크립트 실행 시간이 크게 느려질 수 있으며, 두 번째로 배포가 더 어려워집니다.

그렇다면 이것은 좋은 접근 방법이며 다른 (오픈 소스) 프로젝트도 같은 방식입니까?


4
나는 정말로 긴 쉘 스크립트를 찾고 갔다 . 3500 줄과 125KB에서 나는 그것을 유지하려고하지 않는다. 쉘은 프로그램을 연결할 때 매우 친숙하지만 계산을 시도 할 때 꽤 추악합니다. 나는 당신이 주로 작동하는 코드와 그것을 이식하는 비용이 높다는 것을 알고 있지만, 앞으로 다른 것을 고려하고 싶을 수도 있습니다.
msw 2016 년

1
나는 같은 문제에 부딪쳤다. 적당히 큰 bash 프로젝트 sourceforge.net/projects/duplexpr이 있습니다. 현재 각 스크립트는 자체적으로 포함되어 있지만 모든 공통 기능을 별도의 파일로 옮기고 여러 위치에서 업데이트하지 않아도되는 곳에 포함시킬 생각입니다. 일반적으로, 나는 소스가 아닌 각각의 연속 스크립트를 호출하는 것이 낫다고 생각합니다. 부품을 독립적으로 작동시킬 수 있습니다. 그런 다음 변수 나 인수로 변수를 전달해야합니다 (또는 독립형을 원하지 않으면 내보낼 수 있습니다)
Joe

답변:


13

예, 일반적인 관행입니다. 예를 들어 Unix 초기에는 부팅 단계를 통해 시스템을 다중 사용자 작업으로 안내하는 셸 코드가 단일 파일이었습니다 /etc/rc. 오늘날 부트 프로세스는 많은 쉘 스크립트에 의해 제어되며 기능별로 분류되어 있으며 공통 기능과 변수가 중앙 위치에서 필요에 따라 제공됩니다. Linux 배포판, Mac, BSD는 모두이 접근 방식을 다양한 정도로 채택했습니다.


2
이 경우 재사용 가능성이 더 높습니다. 다른 스크립트는 공통 쉘 함수 라이브러리를 사용합니다.
Stéphane Chazelas

16

이 시점에서 쉘이 작업에 적합한 도구입니까? 코드가 커지는 문제에 부딪힌 개발자는 다시 쓰기를 고려해야한다고 생각할 수 있지만 대신 파이썬이나 루비 또는 펄과 같이 응용 프로그램을 확장하려는 규모에 더 적합한 조각으로 조각을 분리하는 것을 고려할 수 있습니다 ?

셸은 유틸리티 언어이며 스크립트 언어이므로 이러한 크기로 확장하기가 어렵습니다.


이것이 바로 게시하려고하는 내용입니다.
zwol

특히 Solaris와 같은 오래된 OS조차도 현재 perl 및 python 등으로 제공됩니다. 구형 시스템에서 셸 스크립트를 사용하는 한 가지 이유는 셸이 항상 사용 가능하다는 보장이 있었지만 HP-UX 및 Solaris 및 AIX와 같은 더 큰 Unices는 다른 도구를 포함 할 수는 없었습니다.
팀 케네디

7

유지 관리가 더 쉬워지면 둘 다 가질 수 있습니다. 논리적 부분으로 분할하여 쉽게 관리 할 수 ​​있도록 한 다음 Makefile을 작성 (예를 들어) 배포 할 수 있도록 다시 정리하십시오. 빠른 스크립트를 작성하여 포함 파일에서 출력 파일로 대신 함수를 복사 할 수 있습니다. source라인이 아니면 그냥 이런 사소한 일을 (같은 당신이 다시 tabify해야합니다 make탭 필요) :

all: myscript

myscript: includes/* body/*
    cat $^ > "$@" || (rm -f "$@"; exit 1)

그런 다음 "소스"버전 (편집에 사용)과 "이진"버전 (간편한 설치에 사용)이 있습니다.


1
아하! 간단한 고양이 접근 방식을 사용하는 다른 사람 :)
Clayton Stanley

4

설명하는대로 스크립트가 손상 될 수 있습니다. '좋은 접근 방식'은 큰 스크립트를 구획화하고 그 일부가 별도의 프로세스로 실행될 수있는 위치를 파악하여 IPC 메커니즘을 통해 통신하는 것입니다.

그 외에도 쉘 스크립트의 경우 단일 파일로 패키지합니다. 당신이 말했듯이, 배포가 더 어려워집니다 : '라이브러리'스크립트가 어디에 있는지 알아야합니다-쉘 스크립트에는 좋은 표준이 없습니다-또는 경로를 올바르게 설정하기 위해 사용자에게 의존하십시오.

이 모든 것을 처리하는 설치 프로그램을 배포하여 파일을 추출하여 적절한 위치 export PROGRAMDIR=$HOME/lib/PROGRAM에 놓고 ~ / .bashrc 파일 과 같은 것을 추가하도록 사용자에게 지시 할 수 있습니다 . 그러면 $PROGRAMDIR설정되지 않았거나 원하는 파일이 포함되어 있지 않으면 주 프로그램이 실패 할 수 있습니다.

다른 스크립트를로드하는 오버 헤드에 대해서는별로 걱정하지 않습니다. 오버 헤드는 실제로 파일을 여는 것입니다. 텍스트 처리는 특히 함수 정의 인 경우 동일합니다.


1

일반적인 관행이든 아니든 일련의 수출 이외의 것을 소싱하는 것은 좋은 생각이 아닙니다. 소싱하여 코드를 실행하는 것은 혼란스럽고 환경 및 기타 변수 설정으로 인해 소스 코드가 소싱 코드에 크게 의존하기 때문에 재사용이 제한됩니다.

응용 프로그램을 더 작은 자체 포함 스크립트로 분할 한 다음 일련의 명령으로 실행하는 것이 좋습니다. 대화식 쉘에서 각각의 자체 포함 스크립트를 실행하고 각 명령 호출간에 파일, 로그 등을 검사 할 수 있으므로 디버깅이 쉬워집니다. 하나의 큰 응용 프로그램 스크립트는 디버깅을 마친 후에 일련의 명령을 실행하는 간단한 제어 스크립트로 바뀝니다.

더 작고 독립적 인 스크립트 그룹이 설치하기 어려운 문제에 부딪칩니다.


1

스크립트 소싱의 대안은 단순히 인수로 스크립트를 호출하는 것입니다. 대부분의 기능을 이미 셸 함수로 나눈 경우 이미이 작업을 수행 할 수있을 것입니다. 다음 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는 환경 및 옵션 오염을 피하기 위해서입니다.


0

다음은 큰 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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.