Membina dan Memanggil Pustaka Bash Boleh Guna Semula
Susun pembantu dikongsi ke dalam fail pustaka .sh yang boleh dipanggil, dengan pengawal penyertaan dan awalan fungsi bernamespace.
Membina dan Memanggil Pustaka Bash Boleh Guna Semula ialah pelajaran Kem Intensif DevOps percuma di CoddyKit. Ini ialah pelajaran 2 daripada 4. Sebanyak 3 pelajaran dalam laluan pembelajaran ini boleh dibaca sepenuhnya secara percuma — selepas itu, CoddyKit PRO membuka akses kepada semua pelajaran, serta latihan praktikal dengan penyunting kod terbina dalam dan tutor kecerdasan buatan yang tersedia 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran Kem Intensif DevOps, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus Kem Intensif DevOps merangkumi sejumlah 4 pelajaran.
Apakah Itu Pustaka Bash?
Dalam kejuruteraan perisian, pustaka ialah himpunan fungsi yang boleh digunakan semula oleh beberapa program. Bash menyokong konsep yang sama melalui skrip shell yang boleh dimuatkan.
Daripada menyalin dan menampal fungsi pembantu ke dalam setiap skrip, anda meletakkannya dalam fail .sh khusus dan memuatkannya dengan perintah source (atau singkatannya .). Sebarang fungsi, pemboleh ubah atau alias yang ditakrifkan dalam fail itu menjadi tersedia dalam sesi shell semasa skrip pemanggil.
- Menggalakkan prinsip DRY (Jangan Ulangi Diri Sendiri)
- Memusatkan pembaikan pepijat — baiki sekali, semua pemanggil mendapat manfaat
- Menjadikan skrip individu lebih pendek dan mudah dibaca
- Membolehkan konsistensi seluruh pasukan dalam pengelogan, pengendalian ralat dan logik utiliti
Projek Bash yang tersusun baik biasanya mempunyai direktori lib/ yang mengandungi fail kongsi ini, selaras dengan konvensyen bahasa aras lebih tinggi.
Perintah source dan Operator Titik
Terdapat dua cara yang setara untuk memuatkan fail pustaka ke dalam persekitaran shell semasa:
source /path/to/lib.sh— bentuk yang jelas dan mudah dibaca. /path/to/lib.sh— bentuk singkat yang serasi dengan POSIX
Kedua-duanya melaksanakan fail dalam proses shell semasa, bukan subshell, maka setiap fungsi dan pemboleh ubah yang ditakrifkan di dalamnya menjadi sebahagian daripada persekitaran skrip sejurus selepas panggilan tersebut.
Corak lazim ialah mencari lokasi pustaka secara relatif kepada skrip pemanggil menggunakan $BASH_SOURCE, yang menjadikan projek mudah alih tanpa mengira lokasi pemasangannya.
#!/usr/bin/env bash
# main.sh — load a library relative to this script's own location
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/lib/utils.sh"
echo "Library loaded. Calling greet..."
greet "World"Mencipta Fail Pustaka Pertama Anda
Fail pustaka ialah fail .sh biasa yang hanya mengandungi takrif fungsi (dan kadangkala pemalar). Fail ini tidak sepatutnya menjalankan kod yang menghasilkan kesan sampingan pada aras teratas — fail ini bertujuan untuk dimuatkan dengan source, bukan dilaksanakan secara langsung.
Konvensyen utama:
- Mulakan dengan ulasan shebang yang menerangkan tujuan pustaka
- Takrifkan fungsi sahaja — tiada logik
mainpada aras teratas - Gunakan
returndalam fungsi (jangan sekali-kali gunakanexit, kerana tindakan itu akan menghentikan pemanggil) - Simpan fail dalam subdirektori
lib/projek anda
#!/usr/bin/env bash
# lib/utils.sh — General-purpose utility functions
# Print a greeting message
greet() {
local name="${1:-stranger}"
echo "Hello, ${name}!"
}
# Print a timestamped log line to stderr
log_info() {
echo "[INFO] $(date '+%Y-%m-%d %H:%M:%S') $*" >&2
}
# Print an error message and return a failure code
log_error() {
echo "[ERROR] $(date '+%Y-%m-%d %H:%M:%S') $*" >&2
return 1
}Pengawal Sertaan: Mengelakkan Pemuatan Sumber Berganda
Apabila beberapa skrip memuatkan pustaka yang sama, atau apabila sebuah pustaka memuatkan pustaka lain yang turut dimuatkan oleh skrip utama, fungsi boleh ditakrifkan berulang kali. Ini membazirkan masa dan boleh menyebabkan pepijat halus jika badan fungsi digantikan ketika pelaksanaan sedang berjalan.
Penyelesaiannya ialah pengawal sertaan — pemboleh ubah yang bertindak sebagai penanda. Pada pemuatan pertama, pemboleh ubah itu tidak ditetapkan, maka fail diteruskan. Pada setiap pemuatan seterusnya, pengawal itu sudah ditetapkan, maka fail terus pulang.
Ini ialah padanan Bash untuk #pragma once dalam C/C++ atau corak if not already imported dalam bahasa lain.
#!/usr/bin/env bash
# lib/utils.sh — with include guard
# Guard: if already sourced, do nothing
[[ -n "${_LIB_UTILS_LOADED:-}" ]] && return 0
_LIB_UTILS_LOADED=1
greet() {
local name="${1:-stranger}"
echo "Hello, ${name}!"
}
log_info() {
echo "[INFO] $(date '+%Y-%m-%d %H:%M:%S') $*" >&2
}
log_error() {
echo "[ERROR] $(date '+%Y-%m-%d %H:%M:%S') $*" >&2
return 1
}Awalan Fungsi Berruang Nama
Bash mempunyai satu ruang nama global untuk fungsi. Jika dua pustaka masing-masing mentakrifkan fungsi bernama log atau init, takrif kedua akan menimpa takrif pertama secara senyap.
Pertahanan piawai ialah awalan ruang nama: setiap fungsi dalam pustaka diawali dengan nama ringkas pustaka diikuti dua titik bertindih (::) atau garis bawah. Contohnya, pustaka utiliti rentetan menggunakan str::, manakala pustaka fail menggunakan file::.
- Pertembungan menjadi amat sukar berlaku
- Kod pemanggil menerangkan tujuannya sendiri —
str::trimmemberitahu anda dengan tepat lokasi fungsi itu - Kebolehan mencari dengan grep meningkat:
grep 'str::' main.shserta-merta menunjukkan semua panggilan pustaka rentetan
#!/usr/bin/env bash
# lib/str.sh — String utility library (namespaced)
[[ -n "${_LIB_STR_LOADED:-}" ]] && return 0
_LIB_STR_LOADED=1
# Trim leading and trailing whitespace
str::trim() {
local s="$1"
s="${s#"${s%%[![:space:]]*}"}"
s="${s%"${s##*[![:space:]]}"}"
echo "$s"
}
# Convert string to uppercase
str::upper() {
echo "${1^^}"
}
# Convert string to lowercase
str::lower() {
echo "${1,,}"
}
# Check if a string contains a substring
str::contains() {
[[ "$1" == *"$2"* ]]
}Menyusun Direktori lib/
Apabila projek berkembang, satu utils.sh menjadi sukar diurus. Bahagikan tanggungjawab kepada fail pustaka khusus dalam direktori lib/:
lib/log.sh— pembantu pengelogan (log::info,log::warn,log::error)lib/str.sh— manipulasi rentetan (str::trim,str::upper)lib/fs.sh— pembantu sistem fail (fs::require_dir,fs::safe_rm)lib/net.sh— semakan rangkaian (net::wait_for_port,net::is_online)
Satu fail pemuat bootstrap (lib/bootstrap.sh) boleh memuatkan semua fail tersebut mengikut susunan yang betul, supaya setiap skrip hanya memerlukan satu panggilan source.
#!/usr/bin/env bash
# lib/bootstrap.sh — Load all project libraries in dependency order
[[ -n "${_LIB_BOOTSTRAP_LOADED:-}" ]] && return 0
_LIB_BOOTSTRAP_LOADED=1
_BOOTSTRAP_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${_BOOTSTRAP_DIR}/log.sh"
source "${_BOOTSTRAP_DIR}/str.sh"
source "${_BOOTSTRAP_DIR}/fs.sh"
source "${_BOOTSTRAP_DIR}/net.sh"
log::info "All libraries loaded."Pustaka Pengelogan Lengkap
Pengelogan ialah perkara bersama yang paling kerap digunakan merentas skrip. lib/log.sh khusus memusatkan pemformatan keluaran, tahap log dan kod warna.
Dengan adanya pustaka seperti ini, setiap skrip dalam projek mencetak mesej yang konsisten, mempunyai cap masa dan dikodkan warna tanpa menduplikasi sebarang kod pemformatan.
#!/usr/bin/env bash
# lib/log.sh — Coloured, levelled logging library
[[ -n "${_LIB_LOG_LOADED:-}" ]] && return 0
_LIB_LOG_LOADED=1
# Colour codes (disabled when not writing to a terminal)
_LOG_RED=''; _LOG_YEL=''; _LOG_GRN=''; _LOG_RST=''
if [[ -t 2 ]]; then
_LOG_RED='\033[0;31m'
_LOG_YEL='\033[0;33m'
_LOG_GRN='\033[0;32m'
_LOG_RST='\033[0m'
fi
_log::_print() {
local level="$1" colour="$2"; shift 2
printf "%b[%s]%b %s %s\n" \
"$colour" "$level" "$_LOG_RST" \
"$(date '+%H:%M:%S')" "$*" >&2
}
log::info() { _log::_print 'INFO ' "$_LOG_GRN" "$@"; }
log::warn() { _log::_print 'WARN ' "$_LOG_YEL" "$@"; }
log::error() { _log::_print 'ERROR' "$_LOG_RED" "$@"; return 1; }
log::fatal() { _log::_print 'FATAL' "$_LOG_RED" "$@"; exit 1; }Pustaka Pembantu Sistem Fail
Skrip yang memanipulasi fail dan direktori sering mengulangi pemeriksaan pertahanan yang sama: adakah direktori ini wujud? Adakah laluan ini boleh ditulis? Adakah saya akan memadam sesuatu yang penting?
Memusatkan pemeriksaan ini dalam lib/fs.sh menjadikan setiap skrip pengguna lebih selamat dan mudah dibaca. Perhatikan bahawa setiap fungsi menggunakan return 1 apabila gagal, bukannya exit, supaya pemanggil masih boleh mengendalikan ralat dengan baik.
#!/usr/bin/env bash
# lib/fs.sh — Filesystem helper library
[[ -n "${_LIB_FS_LOADED:-}" ]] && return 0
_LIB_FS_LOADED=1
# Ensure a directory exists; create it if not
fs::require_dir() {
local dir="$1"
if [[ ! -d "$dir" ]]; then
mkdir -p "$dir" || { echo "[fs] Cannot create directory: $dir" >&2; return 1; }
fi
}
# Remove a file only if it exists (no error on missing)
fs::safe_rm() {
local target="$1"
[[ -e "$target" ]] && rm -rf -- "$target"
return 0
}
# Assert that a file exists and is readable
fs::require_file() {
local file="$1"
[[ -f "$file" && -r "$file" ]] || {
echo "[fs] Required file missing or unreadable: $file" >&2
return 1
}
}Membuat Versi Pustaka dengan Pemalar
Apabila pustaka anda dikongsi merentas beberapa projek atau diedarkan kepada satu pasukan, penting untuk mengetahui versi yang mana bagi pustaka tersebut dimuatkan semasa masa jalan. Satu konvensyen mudah ialah mengeksport pemalar versi daripada setiap pustaka.
Pemanggil kemudiannya boleh mengesahkan versi minimum semasa permulaan, lalu mengesan ketidakpadanan lebih awal berbanding menyahpepijat kegagalan yang sukar difahami kemudian. Pemboleh ubah pengawal turut berfungsi sebagai rentetan versi, dengan menggabungkan dua tanggungjawab dalam satu pemboleh ubah.
#!/usr/bin/env bash
# lib/str.sh — versioned example
# Guard doubles as the version identifier
[[ -n "${_LIB_STR_LOADED:-}" ]] && return 0
readonly _LIB_STR_LOADED='1.3.0'
# Caller can validate the version
str::version() { echo "$_LIB_STR_LOADED"; }
# ---- Utility functions ----
str::trim() {
local s="$1"
s="${s#"${s%%[![:space:]]*}"}"
s="${s%"${s##*[![:space:]]}"}"
echo "$s"
}
str::repeat() {
local str="$1" count="$2" result=''
for (( i=0; i<count; i++ )); do result+="$str"; done
echo "$result"
}Demo Berdikari: Menggunakan Beberapa Pustaka
Babak ini menunjukkan skrip realistik yang mendapatkan sumber daripada dua pustaka dan menggunakan fungsi daripada setiap satunya. Perhatikan bahawa skrip utama kekal kemas — skrip itu menyatakan niat, manakala semua butiran pelaksanaan berada dalam pustaka.
Skrip ini boleh dijalankan sebagai fail kendiri kerana ia mentakrifkan pustaka secara sebaris menggunakan dokumen here yang ditulis ke fail sementara. Dalam projek sebenar, setiap pustaka akan berada dalam failnya sendiri di bawah lib/.
#!/usr/bin/env bash
# Standalone demo: inline libs written to /tmp, then sourced
set -euo pipefail
# --- Create a temporary lib/log.sh ---
TMPDIR_LIBS="$(mktemp -d)"
trap 'rm -rf "$TMPDIR_LIBS"' EXIT
cat > "${TMPDIR_LIBS}/log.sh" <<'LIBEOF'
[[ -n "${_LIB_LOG_LOADED:-}" ]] && return 0
_LIB_LOG_LOADED=1
log::info() { echo "[INFO] $*"; }
log::error() { echo "[ERROR] $*" >&2; return 1; }
LIBEOF
cat > "${TMPDIR_LIBS}/str.sh" <<'LIBEOF'
[[ -n "${_LIB_STR_LOADED:-}" ]] && return 0
_LIB_STR_LOADED=1
str::upper() { echo "${1^^}"; }
str::trim() { local s="$1"; s="${s#"${s%%[![:space:]]*}"}";
s="${s%"${s##*[![:space:]]}"}" ; echo "$s"; }
LIBEOF
# --- Source both libraries ---
source "${TMPDIR_LIBS}/log.sh"
source "${TMPDIR_LIBS}/str.sh"
# --- Main logic ---
log::info "Libraries loaded successfully."
raw_input=" hello from bash libraries "
trimmed="$(str::trim "$raw_input")"
log::info "Trimmed: '${trimmed}'"
log::info "Uppercased: '$(str::upper "$trimmed")'"Amalan Terbaik dan Perangkap Lazim
Sebelum menghantar pustaka untuk kegunaan pasukan, semak senarai semak ini:
- Pengawal kemasukan — setiap pustaka mesti memilikinya; dokumentasikan nama pemboleh ubah pengawal di bahagian atas
- Tiada kesan sampingan peringkat teratas — jangan sekali-kali menggunakan
cd,echoatau mengubah keadaan global di luar badan fungsi - Gunakan
localuntuk semua pemboleh ubah dalam fungsi — tanpalocal, setiap penetapan akan meresap ke dalam skop pemanggil - Kembalikan nilai, jangan keluar —
exitdalam fail yang mendapatkan sumber akan menamatkan keseluruhan shell pemanggil - Sahkan masukan — semak argumen yang diperlukan dan kembalikan kod ralat yang bermakna apabila argumen tersebut tiada
- Dokumentasikan dengan ulasan — terangkan perkara yang dilakukan oleh setiap fungsi, parameternya dan nilai pulangannya
- Elakkan
set -edalam fail pustaka — pemanggil mungkin mempunyai strategi pengendalian ralat sendiri; biarkan mereka menentukannya
Semakan Pengetahuan: Pengawal Kemasukan
Pertimbangkan projek yang menggunakan main.sh untuk mendapatkan sumber daripada kedua-dua lib/bootstrap.sh dan lib/log.sh, manakala lib/bootstrap.sh juga mendapatkan sumber daripada lib/log.sh secara dalaman. Apakah tujuan utama pengawal kemasukan dalam lib/log.sh?
Ulang Kaji Pelajaran: Pustaka Bash yang Betul
Anda telah mempelajari semua teknik penting untuk membina dan menggunakan pustaka Bash yang boleh digunakan semula. Berikut ialah perkara utama yang perlu diingati:
- Dapatkan sumber dengan
sourceatau.— memuatkan fail ke dalam shell semasa, lalu menjadikan fungsinya tersedia serta-merta - Gunakan
$BASH_SOURCEuntuk menyelesaikan laluan pustaka secara relatif kepada skrip pemanggil, supaya projek kekal mudah alih - Pengawal kemasukan (
[[ -n "${_GUARD:-}" ]] && return 0) menghalang takrifan pendua apabila beberapa fail mendapatkan sumber daripada pustaka yang sama - Awalan ruang nama (
log::,str::,fs::) menghapuskan pertembungan nama fungsi merentas pustaka - Direktori
lib/dengan fail yang berfokus dan mempunyai satu tanggungjawab menjadikan projek besar lebih mudah diselenggara - Pemuat bootstrap (
lib/bootstrap.sh) memberikan setiap skrip satu panggilan sumber untuk memuatkan keseluruhan ekosistem - Jangan sekali-kali menggunakan
exitatau kesan sampingan peringkat teratas dalam fail pustaka — hanya takrifan fungsi dan pemalar yang sepatutnya berada di situ
Gunakan corak ini secara konsisten dan skrip shell anda akan menjadi semodular serta semudah diselenggara seperti kod yang ditulis dalam mana-mana bahasa aras lebih tinggi.
Pelajari Kem Intensif DevOps dengan tutor kecerdasan buatan — percuma
Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.
- Kursus
- 142
- Pelajaran
- 568
Soalan Lazim
Adakah pelajaran “Membina dan Memanggil Pustaka Bash Boleh Guna Semula” percuma?
Ya — sebanyak 3 pelajaran dalam laluan pembelajaran Kem Intensif DevOps, termasuk “Membina dan Memanggil Pustaka Bash Boleh Guna Semula”, boleh dibaca sepenuhnya secara percuma di web ini. Selepas itu, CoddyKit PRO membuka akses kepada semua pelajaran, serta latihan interaktif dengan penyunting kod terbina dalam dan tutor kecerdasan buatan yang tersedia 24/7. Kursus Kem Intensif DevOps merangkumi sejumlah 4 pelajaran.
Apakah yang akan saya pelajari dalam “Membina dan Memanggil Pustaka Bash Boleh Guna Semula”?
Susun pembantu dikongsi ke dalam fail pustaka .sh yang boleh dipanggil, dengan pengawal penyertaan dan awalan fungsi bernamespace. Anda berlatih Kem Intensif DevOps menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.
Adakah saya memerlukan pengalaman untuk memulakan Kem Intensif DevOps?
Tiada pengalaman terdahulu diperlukan. Pembelajaran Kem Intensif DevOps di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 2 daripada 4.
Berapa lamakah pelajaran “Membina dan Memanggil Pustaka Bash Boleh Guna Semula” diambil?
Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.
Bolehkah saya menulis dan menjalankan kod dalam pelajaran Kem Intensif DevOps ini?
Ya. Setiap pelajaran Kem Intensif DevOps menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.
Semua pelajaran dalam kursus ini
- Mereka Bentuk Fungsi dengan Skop Setempat dan Kod Pulangan
- Membina dan Memanggil Pustaka Bash Boleh Guna Semula
- Menghurai Bendera dan Argumen dengan getopts
- Menghantar Tatasusunan dan Peta Bersekutu antara Fungsi