Tan Phat Media

Bash Script Generator

Sinh khung script Bash sẵn phần đọc tham số, log có màu, bẫy lỗi và các khối việc vận hành hay dùng

Thông tin script
Khối nền tảng

set -euo pipefail và IFS thu hẹp

In hướng dẫn khi chạy với -h

debug, info, warn, error kèm dấu thời gian

Xóa thư mục tạm và báo dòng lỗi khi thoát

Thoát sớm nếu máy thiếu lệnh cần dùng

Thoát nếu EUID khác 0

Chỉ một tiến trình chạy tại một thời điểm

Khối việc dựng sẵn
backup-app.sh
278 dòng
7.643 ký tự
set -euo pipefail
usage
log có màu
trap dọn dẹp
kiểm tra lệnh
khóa flock
#!/usr/bin/env bash
#
# backup-app.sh - Sao lưu thư mục ứng dụng và dọn bản sao lưu cũ
# Tác giả: Tấn Phát Digital
# Sinh bởi Bash Script Generator - tanphatdigital.com
#

# -e dừng khi một lệnh trả mã khác 0, -u chặn dùng biến chưa gán,
# pipefail báo lỗi khi bất kỳ khâu nào trong ống dẫn thất bại.
# IFS thu hẹp để vòng lặp không tự tách chuỗi theo dấu cách.
set -euo pipefail
IFS=$'\n\t'

readonly SCRIPT_NAME="$(basename "${BASH_SOURCE[0]}")"
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly SCRIPT_VERSION="1.0.0"

# Cờ toàn cục, được đặt lại bởi khối phân tích tham số bên dưới.
DRY_RUN="false"
VERBOSE="false"
CONFIG_FILE=""
ARGS=()

# --- Màu và mức log ------------------------------------------------------
# Chỉ bật màu khi đầu ra lỗi chuẩn là terminal, để log ghi vào tệp
# hoặc chạy qua cron không dính các ký tự điều khiển màu.
if [[ -t 2 ]]; then
  C_RESET=$'\033[0m'
  C_RED=$'\033[0;31m'
  C_YELLOW=$'\033[0;33m'
  C_GREEN=$'\033[0;32m'
  C_BLUE=$'\033[0;34m'
  C_GRAY=$'\033[0;90m'
else
  C_RESET=""; C_RED=""; C_YELLOW=""; C_GREEN=""; C_BLUE=""; C_GRAY=""
fi
readonly C_RESET C_RED C_YELLOW C_GREEN C_BLUE C_GRAY

# Bốn mức theo thứ tự: debug < info < warn < error.
# Đặt LOG_LEVEL=debug ở đầu dòng lệnh để xem hết, mặc định chỉ từ info.
LOG_LEVEL="${LOG_LEVEL:-info}"
LOG_FILE="${LOG_FILE:-/var/log/backup-app.log}"

log_level_value() {
  case "$1" in
    debug) printf '10' ;;
    info)  printf '20' ;;
    warn)  printf '30' ;;
    error) printf '40' ;;
    *)     printf '20' ;;
  esac
}

log() {
  local level="$1"; shift
  local color="$1"; shift
  local msg="$*"
  local threshold current ts
  threshold="$(log_level_value "$LOG_LEVEL")"
  current="$(log_level_value "$level")"
  if (( current < threshold )); then
    return 0
  fi
  ts="$(date '+%Y-%m-%d %H:%M:%S')"
  printf '%s%s [%-5s] %s%s\n' "$color" "$ts" "$level" "$msg" "$C_RESET" >&2
  if [[ -n "$LOG_FILE" ]]; then
    printf '%s [%-5s] %s\n' "$ts" "$level" "$msg" >>"$LOG_FILE" 2>/dev/null || true
  fi
  return 0
}

log_debug() { log debug "$C_GRAY" "$@"; }
log_info()  { log info  "$C_BLUE" "$@"; }
log_ok()    { log info  "$C_GREEN" "$@"; }
log_warn()  { log warn  "$C_YELLOW" "$@"; }
log_error() { log error "$C_RED" "$@"; }

# --- Trợ giúp ------------------------------------------------------------
usage() {
  cat <<EOF
${SCRIPT_NAME} - Sao lưu thư mục ứng dụng và dọn bản sao lưu cũ

Cách dùng:
  ${SCRIPT_NAME} [TÙY CHỌN]... [ĐỐI SỐ]...

Tùy chọn:
  -h, --help              Hiện trợ giúp này rồi thoát
  -V, --version           Hiện phiên bản rồi thoát
  -v, --verbose           Bật log mức debug
  -n, --dry-run           Chạy thử, chỉ in việc sẽ làm chứ không làm thật
  -c, --config TEP        Đường dẫn tệp cấu hình
      --                  Kết thúc phần tùy chọn, phần còn lại là đối số

Ví dụ:
  ${SCRIPT_NAME} --dry-run --verbose
  ${SCRIPT_NAME} -c /etc/backup-app.conf
EOF
}

# --- Bẫy dọn dẹp ---------------------------------------------------------
# TMP_DIR được tạo trong main. Hàm cleanup xóa nó dù script kết thúc bình
# thường, gặp lỗi, hay bị người dùng bấm Ctrl+C.
TMP_DIR=""
LAST_LINE=""

cleanup() {
  local exit_code=$?
  trap - EXIT INT TERM
  if [[ -n "$TMP_DIR" && -d "$TMP_DIR" ]]; then
    rm -rf -- "$TMP_DIR"
    log_debug "Đã xóa thư mục tạm: $TMP_DIR"
  fi
  if (( exit_code != 0 )); then
    log_error "Script dừng bất thường, mã lỗi $exit_code, dòng ${LAST_LINE:-không rõ}"
  fi
  exit "$exit_code"
}

trap cleanup EXIT INT TERM
trap 'LAST_LINE=$LINENO' ERR

# --- Kiểm tra lệnh phụ thuộc ---------------------------------------------
# Báo hết các lệnh còn thiếu trong một lượt thay vì dừng ở lệnh đầu tiên.
require_cmd() {
  local missing=0 cmd
  for cmd in "$@"; do
    if ! command -v "$cmd" >/dev/null 2>&1; then
      log_error "Thiếu lệnh phụ thuộc: $cmd"
      missing=1
    fi
  done
  if (( missing != 0 )); then
    log_error "Hãy cài đủ các lệnh trên rồi chạy lại."
    exit 127
  fi
}

# --- Khóa chống chạy trùng -----------------------------------------------
# flock giữ khóa trên bộ mô tả tệp số 9. Tiến trình thứ hai không lấy được
# khóa sẽ thoát ngay thay vì chạy song song và giẫm lên nhau.
readonly LOCK_FILE="/var/lock/backup-app.lock"

acquire_lock() {
  exec 9>"$LOCK_FILE"
  if ! flock -n 9; then
    log_error "Một tiến trình khác đang chạy, khóa: $LOCK_FILE"
    exit 1
  fi
  log_debug "Đã giữ khóa: $LOCK_FILE"
}

# --- Việc: sao lưu thư mục thành tệp nén ----------------------------------
do_backup() {
  local src="$1" dest_dir="$2"
  local stamp archive
  if [[ ! -d "$src" ]]; then
    log_error "Không thấy thư mục nguồn: $src"
    return 1
  fi
  stamp="$(date '+%Y%m%d-%H%M%S')"
  archive="${dest_dir}/$(basename "$src")-${stamp}.tar.gz"
  log_info "Sao lưu $src sang $archive"
  if [[ "$DRY_RUN" == "true" ]]; then
    log_warn "Chạy thử: bỏ qua bước tạo tệp nén"
    return 0
  fi
  mkdir -p -- "$dest_dir"
  tar -czf "$archive" -C "$(dirname "$src")" "$(basename "$src")"
  log_ok "Đã tạo bản sao lưu: $archive ($(du -h "$archive" | cut -f1))"
}

# --- Việc: dọn tệp cũ theo số ngày ---------------------------------------
do_cleanup_old() {
  local dir="$1" days="$2" pattern="${3:-*}"
  local count
  if [[ ! -d "$dir" ]]; then
    log_warn "Bỏ qua dọn dẹp, không thấy thư mục: $dir"
    return 0
  fi
  count="$(find "$dir" -maxdepth 1 -type f -name "$pattern" -mtime +"$days" | wc -l | tr -d ' ')"
  log_info "Có $count tệp cũ hơn $days ngày trong $dir"
  if (( count == 0 )); then
    return 0
  fi
  if [[ "$DRY_RUN" == "true" ]]; then
    log_warn "Chạy thử: chỉ liệt kê, không xóa"
    find "$dir" -maxdepth 1 -type f -name "$pattern" -mtime +"$days" -print
    return 0
  fi
  find "$dir" -maxdepth 1 -type f -name "$pattern" -mtime +"$days" -print -delete
  log_ok "Đã dọn xong tệp cũ"
}

# --- Phân tích tham số dòng lệnh ------------------------------------------
# Vòng lặp case đọc được cả cờ ngắn lẫn cờ dài, kể cả dạng --config=giá-trị.
parse_args() {
  while [[ $# -gt 0 ]]; do
    case "$1" in
      -h|--help)
        usage
        exit 0
        ;;
      -V|--version)
        printf '%s %s\n' "$SCRIPT_NAME" "$SCRIPT_VERSION"
        exit 0
        ;;
      -v|--verbose)
        VERBOSE="true"
        LOG_LEVEL="debug"
        shift
        ;;
      -n|--dry-run)
        DRY_RUN="true"
        shift
        ;;
      -c|--config)
        if [[ $# -lt 2 ]]; then
          log_error "Tùy chọn cần một giá trị đi kèm: $1"
          exit 2
        fi
        CONFIG_FILE="$2"
        shift 2
        ;;
      --config=*)
        CONFIG_FILE="${1#*=}"
        shift
        ;;
      --)
        shift
        ARGS+=("$@")
        break
        ;;
      -*)
        log_error "Tùy chọn không hợp lệ: $1"
        usage
        exit 2
        ;;
      *)
        ARGS+=("$1")
        shift
        ;;
    esac
  done
}

# --- Luồng chính ---------------------------------------------------------
main() {
  parse_args "$@"

  require_cmd tar rsync find
  acquire_lock
  TMP_DIR="$(mktemp -d)"

  if [[ -n "$CONFIG_FILE" ]]; then
    if [[ -r "$CONFIG_FILE" ]]; then
      # shellcheck source=/dev/null
      source "$CONFIG_FILE"
      log_info "Đã nạp tệp cấu hình: $CONFIG_FILE"
    else
      log_error "Không đọc được tệp cấu hình: $CONFIG_FILE"
      exit 1
    fi
  fi

  log_info "Bắt đầu $SCRIPT_NAME phiên bản $SCRIPT_VERSION"
  if [[ "$DRY_RUN" == "true" ]]; then
    log_warn "Đang ở chế độ chạy thử, không có thay đổi nào được ghi"
  fi
  log_debug "Đối số còn lại: ${ARGS[*]:-không có}"

  do_backup "/var/www/app" "/backup/app"
  do_cleanup_old "/backup/app" "14" "*.tar.gz"

  log_ok "Hoàn tất"
}

main "$@"

Sau khi tải về, cấp quyền chạy bằng chmod +x rồi kiểm tra cú pháp bằng bash -n trước khi đưa lên máy chủ thật.

Chạy thử an toàn trước khi giao việc thật
chmod +x backup-app.sh
bash -n backup-app.sh
shellcheck backup-app.sh

Lệnh bash -n chỉ đọc cú pháp chứ không chạy lệnh nào bên trong. shellcheck là công cụ ngoài, cài thêm nếu muốn bắt các lỗi tinh vi hơn như thiếu dấu nháy quanh biến.

Công cụ này khác gì các công cụ liên quan

Trang này chỉ sinh ra văn bản script. Nó không chạy lệnh nào, không kết nối tới máy chủ của bạn và không biết trên máy đó đang có gì. Toàn bộ việc ghép chuỗi diễn ra trong trình duyệt.

Cần việc ngược lại hoặc việc lân cận thì dùng đúng công cụ của nó:

  • Bash Command Explainer — chiều ngược lại của trang này. Khi bạn đã có sẵn một dòng lệnh và muốn biết từng cờ nghĩa là gì, dán vào đó. Trang này sinh script mới, trang kia đọc lệnh có sẵn và cảnh báo lệnh nguy hiểm.
  • Crontab Generator — sinh chuỗi năm trường thời gian để hẹn giờ chạy script bạn vừa tải về. Trang này lo phần nội dung script, trang kia lo phần lịch chạy.
  • Chmod Calculator Chmod Generator — tính con số quyền cần cấp cho tệp .sh sau khi tải về, và cho các thư mục mà script sẽ ghi vào.
  • Git Command Generator Git Cheat Sheet — dựng lệnh Git khi script của bạn cần kéo mã nguồn về trước lúc triển khai.

Hợp tác ngay với Tấn Phát Digital

Chúng tôi không chỉ thiết kế website, mà còn giúp doanh nghiệp xây dựng thương hiệu số mạnh mẽ. Cung cấp dịch vụ thiết kế website trọn gói từ thiết kế đến tối ưu SEO. Hãy liên hệ ngay với Tấn Phát Digital để cùng tạo nên những giải pháp công nghệ đột phá, hiệu quả và bền vững cho doanh nghiệp của bạn tại Hồ Chí Minh.

Bash Script Generator: dựng sẵn khung script vận hành đúng chuẩn ngay từ dòng đầu

Công cụ ghép ra một tệp .sh hoàn chỉnh gồm dòng shebang, chế độ nghiêm ngặt, khối đọc tham số dòng lệnh, hàm trợ giúp, hàm log có màu chia bốn mức, bẫy trap dọn dẹp, kiểm tra lệnh phụ thuộc, kiểm tra quyền root, khóa flock chống chạy trùng và bốn khối việc vận hành hay dùng. Bật tắt từng khối rồi chép hoặc tải thẳng tệp .sh về máy.

Tính năng nổi bật

  • Sinh khung script đầy đủ: shebang, set -euo pipefail, IFS thu hẹp và ba hằng số nhận dạng script
  • Chọn kiểu đọc tham số: vòng lặp case có cờ dài như --dry-run, hoặc getopts gọn hơn nhưng chỉ cờ ngắn
  • Hàm log chia bốn mức debug, info, warn, error, tự tắt màu khi ghi ra tệp hoặc chạy qua cron
  • Bẫy trap dọn thư mục tạm và in ra dòng lỗi khi script dừng bất thường hoặc bị bấm Ctrl+C
  • Kiểm tra lệnh phụ thuộc bằng command -v, báo hết các lệnh còn thiếu trong một lượt rồi thoát mã 127
  • Khóa flock trên bộ mô tả tệp số 9 để tiến trình thứ hai thoát ngay thay vì chạy chồng lên nhau
  • Bốn khối việc dựng sẵn: sao lưu thư mục, đồng bộ rsync, dọn tệp cũ theo số ngày, canh dịch vụ systemd
  • Chế độ chạy thử xuyên suốt mọi khối việc, kèm nút chép và nút tải tệp .sh về máy

Vì sao nên bắt đầu từ khung có sẵn thay vì gõ từ đầu

Phần thân của một script vận hành thường chỉ dài mươi dòng, nhưng phần khiến nó chạy an toàn trên máy chủ thì dài gấp năm lần: đọc tham số, in trợ giúp, ghi log kèm dấu thời gian, dọn tệp tạm khi lỗi, kiểm tra máy có đủ lệnh cần dùng chưa, chặn hai bản cùng chạy. Ai cũng biết những phần đó quan trọng, nhưng khi đang vội thì chúng bị bỏ qua đầu tiên, và cái giá phải trả đến muộn: script chạy nửa chừng rồi lỗi, để lại thư mục tạm cả chục gigabyte; cron gọi hai lần trong lúc lần trước chưa xong, hai tiến trình rsync ghi đè lẫn nhau; lệnh chạy trên máy thiếu công cụ nên thất bại im lặng và ba tuần sau mới phát hiện không có bản sao lưu nào. Khung dựng sẵn ở đây gom đúng những phần hay bị bỏ quên đó thành các nút bật tắt. Bạn chọn cái cần, tải tệp về, rồi chỉ viết thêm phần việc riêng của mình. Quan trọng hơn, mã sinh ra có chú thích tiếng Việt ngay tại chỗ, nên khi ba tháng sau bạn hoặc đồng nghiệp mở lại thì vẫn đọc hiểu từng khối làm gì.

Lợi ích khi sử dụng

  • Không phải nhớ cú pháp trap, flock hay getopts mỗi lần viết script mới
  • Chế độ chạy thử có sẵn trong mọi khối việc, thử trước khi để script xóa hay ghi đè thật
  • Mã sinh ra có chú thích tiếng Việt tại chỗ nên người sau đọc lại vẫn hiểu
  • Toàn bộ chạy trong trình duyệt, đường dẫn máy chủ bạn gõ vào không gửi đi đâu cả
  • Tải thẳng tệp .sh, không phải chép qua chép lại rồi lỗi thụt lề

Cách dùng công cụ sinh script Bash

  1. 1Đặt tên tệp, mô tả ngắn và tên tác giả ở khối trên cùng, hoặc bấm một trong bốn mẫu dựng sẵn để nạp nhanh cấu hình thường gặp.
  2. 2Bật tắt các khối nền tảng: chế độ nghiêm ngặt, kiểu đọc tham số, hàm trợ giúp, hàm log, bẫy dọn dẹp, kiểm tra lệnh phụ thuộc, kiểm tra quyền root và khóa flock.
  3. 3Bật các khối việc bạn cần rồi điền đường dẫn thật: thư mục sao lưu, cặp nguồn đích cho rsync, thư mục và số ngày cần dọn, tên dịch vụ systemd cần canh.
  4. 4Đọc lại phần xem trước bên phải, nó cập nhật ngay theo từng thay đổi, rồi bấm nút tải để lấy tệp .sh về máy.
  5. 5Trên máy chủ, chạy chmod +x để cấp quyền, chạy bash -n để kiểm tra cú pháp, rồi chạy với cờ chạy thử một lần trước khi giao cho cron.

set -euo pipefail: ba lớp bảo vệ và những chỗ chúng gây bất ngờ

Cờ -e bảo bash thoát ngay khi một lệnh trả về mã khác không, thay vì chạy tiếp như không có gì xảy ra. Cờ -u biến việc dùng biến chưa gán thành lỗi, đây chính là lớp chặn cho tình huống kinh điển rm -rf $DIR khi DIR rỗng và đường dẫn rút gọn thành thư mục gốc. Còn pipefail đổi cách tính mã trả về của ống dẫn: mặc định bash chỉ lấy mã của lệnh cuối, nên tar czf x.tar.gz thư-mục chạy hỏng mà đưa qua một lệnh khác thành công thì cả ống dẫn vẫn báo thành công. Ba cờ này nên bật mặc định, nhưng cần biết chúng gây bất ngờ ở đâu. Thứ nhất, -e không có hiệu lực với lệnh nằm trong điều kiện if, trong vế trái của && hay ||, nên đừng dựa vào nó để bắt lỗi ở những chỗ đó. Thứ hai, một lệnh trả mã khác không một cách hợp lệ, ví dụ grep không tìm thấy dòng nào, sẽ làm script dừng oan; cách xử lý là viết grep ... || true khi bạn thật sự chấp nhận kết quả rỗng. Thứ ba, với -u thì việc đọc một mảng rỗng theo cú pháp cũ cũng bị coi là lỗi trên bash cũ, nên khung sinh ra dùng dạng có giá trị mặc định để tránh. Dòng IFS đi kèm thu hẹp ký tự tách từ về xuống dòng và tab, giúp vòng lặp không tự cắt đôi đường dẫn có dấu cách.

getopts hay vòng lặp case: chọn theo việc bạn cần cờ dài hay không

getopts là lệnh dựng sẵn của bash, viết ngắn và tự lo phần gom cờ dính nhau, nên gõ -vn hay -v -n đều hiểu như nhau. Nhược điểm lớn nhất là nó chỉ hiểu cờ một ký tự. Muốn có --dry-run hay --config thì phải viết tay vòng lặp while kèm case, và đó là lý do lựa chọn thứ hai tồn tại. Trong khung sinh ra, chuỗi cờ của getopts bắt đầu bằng dấu hai chấm để tắt thông báo lỗi mặc định của bash, nhờ vậy script tự in thông báo bằng tiếng Việt qua nhánh dấu hỏi và nhánh dấu hai chấm. Sau vòng lặp phải có dòng dịch chuyển theo OPTIND thì các đối số còn lại mới về đúng vị trí. Bản dùng vòng lặp case xử lý được cả bốn dạng viết mà người dùng hay gõ: cờ ngắn -c giá-trị, cờ dài --config giá-trị, cờ dài dính dấu bằng --config=giá-trị, và dấu gạch đôi đứng một mình để báo rằng mọi thứ phía sau là đối số chứ không phải cờ. Nó cũng kiểm tra trường hợp người dùng gõ --config mà quên giá trị, thay vì lẳng lặng nuốt luôn đối số kế tiếp. Nếu script chỉ có bạn dùng, getopts là đủ; nếu script giao cho người khác hoặc ghi vào tài liệu vận hành, hãy chọn vòng lặp case vì cờ dài tự nó đã là lời giải thích.

trap và flock: hai thứ chỉ thấy cần khi đã gặp sự cố

Lệnh trap gắn một hàm vào các sự kiện kết thúc. Khung sinh ra bắt ba tín hiệu: EXIT tức mọi đường thoát, INT tức người dùng bấm Ctrl+C, và TERM tức có ai đó gửi lệnh dừng. Hàm dọn dẹp lấy mã thoát ngay dòng đầu vì chỉ ở đó giá trị còn nguyên, sau đó gỡ chính cái bẫy để tránh gọi lại vòng vo, xóa thư mục tạm rồi thoát lại đúng mã cũ. Có thêm một bẫy nữa gắn vào ERR chỉ để ghi lại số dòng gặp lỗi, nhờ vậy thông báo cuối cùng chỉ đúng chỗ hỏng thay vì để bạn dò cả tệp. Còn flock giải quyết một bài toán khác: cron không quan tâm lần chạy trước xong chưa. Một tác vụ sao lưu hẹn mỗi mười lăm phút nhưng có hôm chạy hai mươi phút sẽ tạo ra hai tiến trình cùng ghi vào một thư mục đích. Cách chống là mở một tệp khóa trên bộ mô tả tệp số 9 rồi xin khóa không chờ; xin không được thì thoát ngay. Chọn bộ mô tả 9 vì các số 0, 1, 2 đã dành cho đầu vào, đầu ra và lỗi chuẩn. Khóa tự nhả khi tiến trình kết thúc, kể cả khi bị buộc dừng, nên không có chuyện khóa mắc kẹt vĩnh viễn.

Bốn khối việc dựng sẵn và những chỗ hay sai khi vận hành thật

Khối sao lưu gói một thư mục thành tệp .tar.gz có gắn dấu thời gian theo định dạng năm tháng ngày giờ phút giây, nhờ đó tên tệp sắp xếp theo bảng chữ cái cũng chính là sắp xếp theo thời gian. Nó chuyển vào thư mục cha rồi mới gói để tệp lưu trữ không chứa cả đường dẫn tuyệt đối bên trong, đây là lỗi khiến nhiều bản sao lưu bung ra sai chỗ. Khối rsync dùng bộ tùy chọn giữ nguyên quyền và thời gian, có nén trên đường truyền, kèm cờ xóa ở đích những gì không còn ở nguồn; cờ xóa này mạnh nên chế độ chạy thử tự thêm cờ chạy thử của chính rsync để bạn xem trước danh sách. Khối dọn tệp cũ đếm số tệp khớp trước rồi mới xóa, và giới hạn độ sâu ở một mức để không lỡ tay quét xuống các thư mục con; lưu ý mốc ngày của find tính theo bội số hai mươi tư giờ trọn vẹn, nên +14 nghĩa là cũ hơn mười bốn ngày tròn chứ không phải trước ngày thứ mười bốn. Khối canh dịch vụ hỏi trạng thái bằng lệnh kiểm tra im lặng, chỉ khởi động lại khi dịch vụ thật sự chết, chờ hai giây rồi hỏi lại lần nữa, và nếu vẫn hỏng thì in hai mươi dòng trạng thái gần nhất để bạn có manh mối.

Đưa script lên máy chủ: quyền, đường dẫn và môi trường của cron

Tệp tải về chưa có quyền chạy, phải cấp bằng chmod +x, thường là 755 cho script dùng chung và 700 nếu bên trong có thông tin nhạy cảm. Nơi đặt hợp lý cho script quản trị là /usr/local/bin hoặc một thư mục riêng của dự án, tránh để trong thư mục người dùng vì cron của root sẽ không đọc được. Trước khi chạy lần đầu, hãy dùng bash -n để kiểm tra cú pháp mà không thực thi lệnh nào, rồi chạy với cờ chạy thử. Cạm bẫy lớn nhất khi chuyển sang cron là môi trường: cron không đọc tệp khởi tạo shell của bạn, biến PATH thường chỉ còn vài thư mục cơ bản, nên lệnh nào cài ở /usr/local/bin có thể không tìm thấy dù gõ trực tiếp trên terminal vẫn chạy. Cách chống là ghi đường dẫn tuyệt đối, hoặc đặt lại PATH ngay đầu script. Kế đến là đầu ra: cron gửi mọi thứ script in ra qua thư nội bộ, thứ mà hầu như không ai đọc, nên hãy chuyển hướng cả đầu ra chuẩn lẫn lỗi chuẩn vào một tệp log bằng hai dấu lớn hơn kèm 2>&1. Cuối cùng là thư mục làm việc: cron bắt đầu ở thư mục nhà, nên mọi đường dẫn tương đối trong script sẽ trỏ sai; khung sinh ra có sẵn hằng số giữ thư mục chứa script để bạn dựa vào đó thay vì dùng đường dẫn tương đối.

Câu hỏi thường gặp (FAQ)

Script sinh ra có chạy được trên macOS không?

Phần lớn khối chạy được, nhưng ba chỗ khác biệt cần sửa: lệnh flock không có sẵn trên macOS, lệnh systemctl chỉ có trên Linux dùng systemd, và một số cờ của find hay date theo chuẩn BSD nên viết khác bản GNU. Nếu đích đến là máy chủ Linux thì cứ tải về rồi thử thẳng trên đó.

Vì sao dùng /usr/bin/env bash mà không phải /bin/bash?

Cách viết qua env tìm bash theo biến PATH nên chạy được cả khi bash nằm ở chỗ khác, ví dụ bản bash 5 cài thêm trên macOS ở đường dẫn của trình quản lý gói. Nếu môi trường của bạn cố định và cần chắc chắn dùng đúng bash hệ thống, đổi dòng đầu thành đường dẫn tuyệt đối.

Chế độ chạy thử có thật sự an toàn tuyệt đối không?

Nó chặn các bước ghi và xóa trong bốn khối việc dựng sẵn: không tạo tệp nén, không xóa tệp cũ, rsync chuyển sang chế độ liệt kê, không khởi động lại dịch vụ. Nhưng nếu bạn viết thêm lệnh của mình vào script thì phải tự kiểm tra biến chạy thử trước khi làm việc thật, công cụ không tự bọc giúp phần bạn viết thêm.

Log ghi ra tệp bị dính các ký tự lạ thì xử lý thế nào?

Khung sinh ra đã chống việc này bằng cách chỉ bật màu khi lỗi chuẩn là terminal. Nếu vẫn thấy ký tự lạ, khả năng cao bạn đang chuyển hướng bằng cách khác hoặc dùng lệnh ghi log riêng. Kiểm tra lại khối kiểm tra terminal ở đầu tệp, đó là chỗ quyết định có màu hay không.

Đặt tệp khóa ở đâu cho đúng?

Thư mục /var/lock hoặc /run/lock là nơi chuẩn cho script chạy bằng root. Script chạy bằng tài khoản thường có thể không ghi được vào đó, khi ấy hãy đổi sang một đường dẫn trong /tmp hoặc trong thư mục dự án. Tệp khóa không cần xóa sau khi chạy vì khóa tự nhả khi tiến trình kết thúc.

Vì sao thoát bằng mã 127 khi thiếu lệnh phụ thuộc?

Theo quy ước của shell, mã 127 nghĩa là không tìm thấy lệnh. Dùng đúng mã quy ước giúp hệ thống giám sát phân biệt được lỗi thiếu công cụ với lỗi nghiệp vụ. Tương tự, mã 2 dùng cho tham số sai và mã 1 cho lỗi chung.

Tôi bật kiểm tra root nhưng vẫn muốn chạy thử bằng tài khoản thường?

Hãy tắt nút kiểm tra root khi tải bản để thử, rồi bật lại cho bản chạy thật. Cách khác là chạy qua sudo ngay từ đầu. Đừng sửa điều kiện kiểm tra thành luôn đúng vì như vậy các lệnh cần quyền cao bên trong sẽ thất bại giữa chừng, khó gỡ hơn nhiều.

Cron gọi script mà không thấy chạy, phải xem ở đâu?

Trước hết kiểm tra dòng crontab có ghi đường dẫn tuyệt đối chưa và có chuyển hướng log chưa. Sau đó xem tệp log bạn đã khai. Nếu tệp log rỗng hoàn toàn, nhiều khả năng cron không gọi được script vì thiếu quyền chạy hoặc sai đường dẫn, hãy xem log của chính dịch vụ cron.

Có thêm được khối việc riêng của tôi vào không?

Công cụ chỉ sinh bốn khối dựng sẵn, nhưng tệp tải về là mã Bash thường nên bạn viết thêm hàm của mình rồi gọi trong main. Hãy giữ đúng quy ước sẵn có: dùng các hàm log thay cho lệnh in thẳng, và kiểm tra biến chạy thử trước mọi thao tác ghi hoặc xóa.

Công cụ có gửi đường dẫn tôi nhập lên máy chủ không?

Không. Toàn bộ việc ghép chuỗi chạy trong trình duyệt, không có lệnh gọi mạng nào, và nút tải chỉ tạo tệp ngay trên máy bạn. Vì vậy bạn nhập được cả đường dẫn nội bộ, tên máy chủ hay tên dịch vụ thật mà không lo lộ ra ngoài.

Có nên đưa mật khẩu hay khóa vào thẳng script không?

Không nên. Hãy để chúng trong một tệp cấu hình riêng đặt quyền 600 rồi nạp qua cờ --config mà khung đã hỗ trợ, hoặc dùng biến môi trường. Script thường nằm trong kho mã nguồn và có quyền đọc rộng hơn bạn nghĩ, còn tệp cấu hình thì không.

Công cụ này khác gì Bash Command Explainer trên cùng trang web?

Hai công cụ ngược chiều nhau. Trang này sinh ra script mới từ các lựa chọn của bạn. Bash Command Explainer nhận một dòng lệnh đã có sẵn rồi tách ra giải thích từng cờ, từng toán tử, kèm cảnh báo lệnh nguy hiểm. Viết mới thì dùng trang này, đọc hiểu lệnh người khác đưa thì dùng trang kia.

Từ khóa liên quan

  • tạo script bash online
  • bash script generator
  • mẫu script bash chuẩn
  • set -euo pipefail nghĩa là gì
  • getopts trong bash
  • đọc tham số dòng lệnh bash
  • hàm log có màu trong bash
  • trap bash dọn dẹp khi thoát
  • flock chống chạy trùng cron
  • script sao lưu thư mục tự động
  • script rsync đồng bộ máy chủ
  • xóa file cũ hơn 30 ngày bằng find
  • script kiểm tra dịch vụ systemd
  • viết script chạy cron trên vps
  • kiểm tra lệnh tồn tại trong bash
  • shebang usr bin env bash
  • dry run trong shell script
  • chmod +x cấp quyền chạy script
  • bash -n kiểm tra cú pháp script
  • template shell script vận hành

Công cụ Developer Tools liên quan

.env Generator

Tạo file .env và .env.example cho dự án.

.gitignore Generator

Tạo .gitignore cho Node.js, Python, Java.

API Mock Generator

Tạo mock JSON data cho API testing.

API Response Formatter

Format và phân tích API response.

API Tester

Test REST API: GET, POST, PUT, DELETE.

Postman Alternative - API Testing Tool Online với Collections, Environment & File Upload

Postman Alternative miễn phí - Test APIs với Collections, Multiple Environments, Pre-request Scripts, Collection Runner, File Upload (form-data), Tests/Assertions, Code Generation (cURL, JS, Python, Node.js). Browser-based, không cần cài đặt. Save requests, export/import collections, auto-save history. Hỗ trợ Bearer Token, Basic Auth, API Key. Hoàn hảo cho API development và testing.

Swagger API Tester - Test API với OpenAPI/Swagger Spec & Authentication Online

Swagger API Tester miễn phí - Import OpenAPI/Swagger specification và test API endpoints với đầy đủ authentication (Bearer Token/JWT, Basic Auth, API Key). Hỗ trợ OpenAPI 3.0, Swagger 2.0, auto-parse endpoints, parameters, request body. Giao diện như Swagger UI với color-coded methods, grouped endpoints, real-time testing. Hoàn hảo cho API development, testing, debugging secured APIs.

Base Converter

Chuyển đổi Binary, Hex, Base32.

Base64 Encoder

Mã hóa/giải mã Base64.

Binary Converter

Chuyển đổi Decimal, Binary, Hex.

Box Shadow Generator

Tạo CSS box-shadow trực quan.

Chmod Calculator

Tính quyền file Linux.

Dịch vụ của Tấn Phát Digital

Đang xây sản phẩm và cần thêm người làm phần nặng?

Gói giải pháp doanh nghiệp

Nền tảng custom cho ngân hàng, y tế và sàn B2B, chuẩn ISO 27001, GDPR, PCI-DSS, SLA 99.99%.

Từ 50.000.000đXem chi tiết →

Dịch vụ phát triển Blockchain & Web3

Smart contract, dApp và NFT marketplace đa chuỗi, audit bảo mật đầy đủ trước khi lên mainnet.

Từ 50.000.000đXem chi tiết →

Dịch vụ thiết kế website tại Hồ Chí Minh

Website doanh nghiệp, bán hàng và đặt lịch, chuẩn SEO ngay từ cấu trúc, tốc độ tải dưới 3 giây.

Từ 5.000.000đXem chi tiết →

Dịch vụ thiết kế landing page

Trang đích riêng cho từng chiến dịch quảng cáo, tỷ lệ chuyển đổi 3–8%, bàn giao trong 5–21 ngày.

Từ 3.000.000đXem chi tiết →

Tư vấn và báo giá miễn phí trong 24 giờ. Xem toàn bộ dịch vụ

Zalo
Facebook
Tấn Phát Digital
Zalo
Facebook