เป็นเรื่องปกติหรือไม่ที่จะแบ่งสคริปต์ขนาดใหญ่ออกเป็นหลาย ๆ สคริปต์และส่งมาที่สคริปต์หลัก


23

ในขณะนี้ฉันกำลังพัฒนาสคริปต์ Bash ที่มีขนาดใหญ่ขึ้น (มันเป็นโครงการโอเพ่นซอร์สของฉัน) และมันเริ่มเป็นระเบียบ ฉันแบ่งลอจิกเป็นฟังก์ชันใช้ตัวแปรท้องที่ที่ฉันสามารถและได้ประกาศตัวแปรระดับโลกเพียงเล็กน้อยเท่านั้น ถึงกระนั้นมันก็ค่อนข้างยากที่จะรักษา

ฉันคิดถึงการแบ่งสคริปต์ออกเป็นหลาย ๆ สคริปต์และส่งมาที่สคริปต์หลักของฉัน (คล้ายกับการนำเข้าในภาษาอื่น)

แต่ฉันสงสัยว่านี่เป็นวิธีที่เป็นไปได้หรือไม่ อย่างแรกการจัดหาหลายสคริปต์อาจทำให้เวลาในการประมวลผลของสคริปต์ช้าลงและอย่างที่สองคือทำให้การกระจายยากขึ้น

นี่เป็นวิธีการที่ดีหรือไม่และโครงการอื่น ๆ (Open Source) ทำเช่นเดียวกันหรือไม่


4
ฉันไปหาเชลล์สคริปต์ที่ยาวจริงๆและที่ 3,500 บรรทัดและ 125KB ฉันไม่ต้องการพยายามบำรุงรักษา เชลล์นั้นเป็นมิตรจริง ๆ เมื่อเชื่อมต่อโปรแกรม แต่เมื่อพยายามทำการคำนวณมันก็น่าเกลียด ฉันรู้ว่ารหัสที่คุณใช้งานได้เป็นส่วนใหญ่และค่าใช้จ่ายในการย้ายจะสูง แต่คุณอาจต้องการพิจารณาอย่างอื่นในอนาคต
msw

1
ฉันพบปัญหาเดียวกัน ผมมีโครงการขนาดใหญ่ทุบตีปานกลางsourceforge.net/projects/duplexpr ปัจจุบันสคริปต์แต่ละตัวมีอยู่ในตัวเอง แต่ฉันกำลังคิดที่จะย้ายฟังก์ชั่นทั่วไปทั้งหมดไปยังไฟล์แยกต่างหาก โดยทั่วไปฉันคิดว่ามันจะเป็นการดีกว่าที่จะเรียกสคริปต์ต่อเนื่องแต่ละฉบับแทนที่จะส่งมาที่สคริปต์ มันทำให้ชิ้นส่วนทำงานได้อย่างอิสระ จากนั้นคุณต้องผ่านตัวแปรเป็นข้อโต้แย้งหรือในแฟ้มพารามิเตอร์ (หรือคุณก็สามารถส่งออกได้ถ้าคุณไม่ต้องการแบบสแตนด์อโลน.)
โจ

คำตอบ:


13

ใช่มันเป็นเรื่องธรรมดา /etc/rcยกตัวอย่างเช่นในวันแรกของการใช้ระบบปฏิบัติการยูนิกซ์รหัสเปลือกที่รับผิดชอบในการชี้แนะระบบผ่านขั้นตอนการบูตในการดำเนินงานที่ผู้ใช้หลายคนเป็นไฟล์เดียว ทุกวันนี้กระบวนการบู๊ตถูกควบคุมโดยเชลล์สคริปต์จำนวนมากแยกตามฟังก์ชั่นโดยมีฟังก์ชั่นทั่วไปและตัวแปรที่มาจากที่ต้องการจากที่ตั้งส่วนกลาง การแจกแจงลินุกซ์, Macs, BSD ทั้งหมดได้นำวิธีการนี้ไปใช้ในระดับที่แตกต่างกัน


2
ถึงแม้ว่าในกรณีนี้มันสามารถนำกลับมาใช้ได้อีก สคริปต์ต่าง ๆ ใช้ไลบรารีทั่วไปของฟังก์ชันเชลล์
Stéphane Chazelas

16

เชลล์เป็นเครื่องมือที่เหมาะสมสำหรับงาน ณ จุดนั้นหรือไม่? ในฐานะนักพัฒนาที่ชนรหัส outgrowing ฉันสามารถบอกคุณได้ว่าการเขียนไม่ควรพิจารณา แต่แทนที่จะพิจารณาแยกชิ้นออกเป็นสิ่งที่ดีกว่าเหมาะสำหรับขนาดที่คุณต้องการเติบโตใบสมัครของคุณ - บางทีหลามหรือทับทิมหรือแม้แต่ Perl ?

เชลล์เป็นภาษายูทิลิตี้ - มันเป็นภาษาสคริปต์ - และมันจะยากที่จะเติบโตตามขนาดเหล่านั้น


นี่คือสิ่งที่ฉันกำลังจะโพสต์
zwol

โดยเฉพาะอย่างยิ่งเนื่องจากแม้แต่ OS รุ่นเก่าอย่าง Solaris ก็มีการจัดส่งพร้อม perl และ python และอื่น ๆ ในตอนนี้ เหตุผลหนึ่งที่ระบบเก่าใช้เชลล์สคริปต์คือเชลล์รับประกันว่าจะใช้ได้เสมอ แต่ Unices ที่ใหญ่กว่าเช่น HP-UX และ Solaris และ AIX ไม่สามารถรับประกันได้ว่าจะรวมเครื่องมืออื่น ๆ
Tim Kennedy

7

หากการบำรุงรักษาของคุณง่ายขึ้นคุณสามารถมีได้ทั้งคู่ แยกมันออกเป็นส่วนตรรกะเพื่อให้คุณสามารถรักษาได้อย่างง่ายดายจากนั้นเขียน (เช่น) Makefile เพื่อนำกลับมารวมกันเพื่อการแจกจ่ายคุณสามารถเขียนสคริปต์อย่างรวดเร็วเพื่อคัดลอกฟังก์ชันจากไฟล์ include ไปยังไฟล์เอาต์พุตแทนsourceline หรือเพียงแค่ทำบางสิ่งบางอย่างเล็ก ๆ น้อย ๆ เช่นนี้ (คุณจะต้อง re-tabify นี้เป็นmakeต้องใช้แท็บ):

all: myscript

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

จากนั้นคุณมีรุ่น "แหล่งที่มา" (ใช้สำหรับการแก้ไข) และรุ่น "ไบนารี" (ใช้สำหรับการติดตั้งเล็กน้อย)


1
Aha! คนอื่นที่ใช้วิธีการที่เรียบง่ายแมว :)
เคลย์ตันสแตนลี่ย์

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

นี่คือตัวอย่างของวิธีที่สามารถแบ่งสคริปต์ทุบตีขนาดใหญ่เป็นหลายไฟล์แล้วสร้างเป็นสคริปต์ที่เกิดขึ้นหนึ่งรายการ: 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.