Hướng dẫn bash script chkconfig trong linux - bash script chkconfig trong linux

chkconfig - cập nhật và truy vấn thông tin runlevel cho các dịch vụ hệ thống

Tóm tắc

chkconfig --list [ name ] chkconfig --add tên chkconfig --del tên chkconfig [--level levels ] tên chkconfig [--level levels ] tên
chkconfig --add tên
chkconfig --del tên
chkconfig [--level levels ] tên
chkconfig [--level levels ] tên

Sự miêu tả

chkconfig cung cấp một công cụ dòng lệnh đơn giản để duy trì hệ thống phân cấp thư mục /etc/rc[0-6].d bằng cách giảm các quản trị viên hệ thống của nhiệm vụ trực tiếp thao tác nhiều liên kết tượng trưng trong các thư mục đó.

Việc triển khai chkconfig này được lấy cảm hứng từ lệnh chkconfig có trong hệ điều hành IRIX. Thay vì duy trì thông tin cấu hình bên ngoài phân cấp /etc/rc[0-6].d, tuy nhiên, phiên bản này trực tiếp quản lý các liên kết tượng trưng trong /etc/rc[0-6].d. Điều này để lại tất cả thông tin cấu hình về những dịch vụ init bắt đầu ở một vị trí duy nhất.

chkconfig có năm chức năng riêng biệt: thêm dịch vụ mới cho quản lý, xóa dịch vụ khỏi quản lý, liệt kê thông tin khởi động hiện tại cho dịch vụ, thay đổi thông tin khởi động cho dịch vụ và kiểm tra trạng thái khởi động của một dịch vụ cụ thể.

Khi chkconfig được chạy mà không có bất kỳ tùy chọn nào, nó sẽ hiển thị thông tin sử dụng. Nếu chỉ có một tên dịch vụ được cung cấp, nó sẽ kiểm tra xem dịch vụ có được cấu hình để bắt đầu trong runlevel hiện tại hay không. Nếu đúng, chkconfig trả về true; nếu không nó sẽ trả về sai. Tùy chọn --level có thể được sử dụng để truy vấn havechkconfig một runlevel thay thế thay vì hiện tại.

Nếu một trong những ngày, tắt, hoặc thiết lập lại được xác định sau tên dịch vụ, chkconfig thay đổi thông tin khởi động cho dịch vụ được chỉ định. Các cờ bật và tắt làm cho dịch vụ được khởi động hoặc dừng lại, tương ứng, trong các runlevel được thay đổi. Cờ đặt lại đặt lại thông tin khởi động cho dịch vụ thành bất kỳ thông tin nào được chỉ định trong init script được đề cập.

Theo mặc định, các tùy chọn bật và tắt chỉ ảnh hưởng đến runlevels 2, 3, 4 và 5, trong khi thiết lập lại ảnh hưởng đến tất cả các runlevel. Tùy chọn --level có thể được sử dụng để chỉ định runlevel nào bị ảnh hưởng.

Lưu ý rằng đối với mỗi dịch vụ, mỗi runlevel có một kịch bản bắt đầu hoặc một kịch bản lệnh dừng. Khi chuyển runlevel, init sẽ không khởi động lại một dịch vụ đã được khởi động, và sẽ không dừng lại một dịch vụ không chạy.

Tùy chọn

- cấp độ

Chỉ định các mức chạy mà một hoạt động phải liên quan đến. Nó được đưa ra như một chuỗi các số từ 0 đến 7. Ví dụ, --level 35 chỉ định runlevel 3 và 5.

--thêm tên

Tùy chọn này thêm một dịch vụ mới cho quản lý bởi chkconfig. Khi một dịch vụ mới được thêm vào, chkconfig đảm bảo rằng dịch vụ có thể bắt đầu hoặc một mục nhập giết trong mỗi lần chạy. Nếu bất kỳ runlevel nào thiếu mục nhập như vậy, chkconfig sẽ tạo mục nhập thích hợp như được chỉ định bởi các giá trị mặc định trong init script. Lưu ý rằng các mục mặc định trong các phần 'INIT INFO' được phân tách bằng LSB được ưu tiên hơn runlevel mặc định trong bản initscript.

--tên tên

Dịch vụ này được xóa khỏi quản lý chkconfig và mọi liên kết tượng trưng trong /etc/rc[0-6].d liên quan đến nó sẽ bị xóa.

--tên danh sách

Tùy chọn này liệt kê tất cả các dịch vụ mà chkconfig biết, và liệu chúng có bị dừng hay bắt đầu trong mỗi runlevel hay không. Nếu tên được chỉ định, thông tin chỉ hiển thị về tên dịch vụ.

Tệp Runlevel

Mỗi dịch vụ cần được quản lý bởi chkconfig cần hai hoặc nhiều dòng nhận xét được thêm vào tập lệnh init.d của nó. Dòng đầu tiên cho biết chkconfig những gì runlevels dịch vụ nên được bắt đầu theo mặc định, cũng như các mức độ ưu tiên bắt đầu và dừng. Nếu dịch vụ không nên, theo mặc định, được bắt đầu trong bất kỳ runlevel nào, a - nên được sử dụng thay cho danh sách runlevels. Dòng thứ hai chứa một mô tả cho dịch vụ và có thể được mở rộng trên nhiều dòng với tiếp tục dấu gạch chéo ngược.

Ví dụ, random.init có ba dòng sau:

# chkconfig: 2345 20 80 # Mô tả: Lưu và khôi phục hệ thống entropy pool cho \ # chất lượng cao hơn tạo số ngẫu nhiên.

Điều này nói rằng kịch bản ngẫu nhiên nên được bắt đầu ở cấp 2, 3, 4 và 5, rằng ưu tiên bắt đầu của nó phải là 20 và mức độ ưu tiên dừng của nó phải là 80. Bạn có thể tìm ra mô tả cho biết; \ làm cho dòng được tiếp tục. Không gian thêm ở phía trước của dòng được bỏ qua.

Write Linux Init Script

Như ở bài viết Managing services with update-rc.d mình đã giới thiệu cách sử dụng update-rc.d để cho một service script chạy khi khởi động. Hôm nay mình sẽ giới thiệu cách viết một service script đơn giản nhất [cũng đầy đủ chức năng cơ bản là start, stop, restart và status]. Chúng ta sẽ viết service cho Unicorn nhé.Managing services with update-rc.d mình đã giới thiệu cách sử dụng update-rc.d để cho một service script chạy khi khởi động. Hôm nay mình sẽ giới thiệu cách viết một service script đơn giản nhất [cũng đầy đủ chức năng cơ bản là start, stop, restartstatus]. Chúng ta sẽ viết service cho Unicorn nhé.

Nguyên liệu

Về phần nguyên liệu, chúng ta sẽ thử nghiệm luôn trên local cho nhanh [đỡ phải động chạm đến server hoặc đỡ phải cài cắm quá nhiều - nếu bạn dùng Docker].

Source code

Bạn có thể sử dụng ngay //github.com/namnv609/test-deploy-ruby-v3 này của mình cho tiện nhé. Clone nó về máy và duplicate file

# /etc/hosts
127.0.0.1   sample-app.local
6 thành
# /etc/hosts
127.0.0.1   sample-app.local
7 rồi sửa lại line 1 chỗ
# /etc/hosts
127.0.0.1   sample-app.local
8 cho phù hợp với đường dẫn của project.

Tiếp theo, bạn sửa lại nội dung của file

# /etc/hosts
127.0.0.1   sample-app.local
9 ở phần
#!/bin/bash
#
# chkconfig:            2345 70 30
# description:          Sample app Unicorn
# processname:          unicorn
#
### BEGIN INIT INFO
# Provides:             unicorn
# Required-Start:       $remote_fs $syslog
# Required-Stop:        $remote_fs $syslog
# Default-Start:        2 3 4 5
# Default-Stop:         0 1 6
# Short-Description:    Start Rails app at boot time
# Description:          Enable Rails app running by Unicorn daemon
### END INIT INFO
0 và
#!/bin/bash
#
# chkconfig:            2345 70 30
# description:          Sample app Unicorn
# processname:          unicorn
#
### BEGIN INIT INFO
# Provides:             unicorn
# Required-Start:       $remote_fs $syslog
# Required-Stop:        $remote_fs $syslog
# Default-Start:        2 3 4 5
# Default-Stop:         0 1 6
# Short-Description:    Start Rails app at boot time
# Description:          Enable Rails app running by Unicorn daemon
### END INIT INFO
1 cho phù hợp là xong.

Nginx

Phần cài đặt này là để chúng ta access vào web thông qua socket của Unicorn với Nginx. Các bạn thực hiện theo các bước sau:

  1. Tạo một file cấu hình cho Nginx trong thư mục

    #!/bin/bash
    #
    # chkconfig:            2345 70 30
    # description:          Sample app Unicorn
    # processname:          unicorn
    #
    ### BEGIN INIT INFO
    # Provides:             unicorn
    # Required-Start:       $remote_fs $syslog
    # Required-Stop:        $remote_fs $syslog
    # Default-Start:        2 3 4 5
    # Default-Stop:         0 1 6
    # Short-Description:    Start Rails app at boot time
    # Description:          Enable Rails app running by Unicorn daemon
    ### END INIT INFO
    
    2, mình lấy tạm tên là
    #!/bin/bash
    #
    # chkconfig:            2345 70 30
    # description:          Sample app Unicorn
    # processname:          unicorn
    #
    ### BEGIN INIT INFO
    # Provides:             unicorn
    # Required-Start:       $remote_fs $syslog
    # Required-Stop:        $remote_fs $syslog
    # Default-Start:        2 3 4 5
    # Default-Stop:         0 1 6
    # Short-Description:    Start Rails app at boot time
    # Description:          Enable Rails app running by Unicorn daemon
    ### END INIT INFO
    
    3 và thêm nội dung sau [các bạn nhớ thay placeholder
    #!/bin/bash
    #
    # chkconfig:            2345 70 30
    # description:          Sample app Unicorn
    # processname:          unicorn
    #
    ### BEGIN INIT INFO
    # Provides:             unicorn
    # Required-Start:       $remote_fs $syslog
    # Required-Stop:        $remote_fs $syslog
    # Default-Start:        2 3 4 5
    # Default-Stop:         0 1 6
    # Short-Description:    Start Rails app at boot time
    # Description:          Enable Rails app running by Unicorn daemon
    ### END INIT INFO
    
    4 cho phù hợp]:

    upstream test_deploy_v3 {
      server unix:/tmp/sockets/unicorn.sock fail_timeout=0;
    }
    
    server {
      listen 80;
      server_name sample-app.local;
      root /public;
    
      location ^~ /assets/ {
        gzip_static on;
        expires max;
        add_header Cache-Control public;
      }
    
      location ~ ^/[robots.txt|sitemap.xml.gz]/ {
        root /public;
      }
    
      try_files $uri/index.html $uri @test_deploy_v3;
      location @test_deploy_v3 {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_pass //test_deploy_v3;
      }
    
      error_page 500 502 503 504 /500.html;
      client_max_body_size 4G;
      keepalive_timeout 10;
    }
    
  2. Enable Nginx config bằng lệnh sau:

    #!/bin/bash
    #
    # chkconfig:            2345 70 30
    # description:          Sample app Unicorn
    # processname:          unicorn
    #
    ### BEGIN INIT INFO
    # Provides:             unicorn
    # Required-Start:       $remote_fs $syslog
    # Required-Stop:        $remote_fs $syslog
    # Default-Start:        2 3 4 5
    # Default-Stop:         0 1 6
    # Short-Description:    Start Rails app at boot time
    # Description:          Enable Rails app running by Unicorn daemon
    ### END INIT INFO
    
    5

  3. Khởi động lại Nginx để áp dụng các cài đặt:

    #!/bin/bash
    #
    # chkconfig:            2345 70 30
    # description:          Sample app Unicorn
    # processname:          unicorn
    #
    ### BEGIN INIT INFO
    # Provides:             unicorn
    # Required-Start:       $remote_fs $syslog
    # Required-Stop:        $remote_fs $syslog
    # Default-Start:        2 3 4 5
    # Default-Stop:         0 1 6
    # Short-Description:    Start Rails app at boot time
    # Description:          Enable Rails app running by Unicorn daemon
    ### END INIT INFO
    
    6

  4. Thêm sample-app.local vào file

    #!/bin/bash
    #
    # chkconfig:            2345 70 30
    # description:          Sample app Unicorn
    # processname:          unicorn
    #
    ### BEGIN INIT INFO
    # Provides:             unicorn
    # Required-Start:       $remote_fs $syslog
    # Required-Stop:        $remote_fs $syslog
    # Default-Start:        2 3 4 5
    # Default-Stop:         0 1 6
    # Short-Description:    Start Rails app at boot time
    # Description:          Enable Rails app running by Unicorn daemon
    ### END INIT INFO
    
    7 để có thể truy cập vào ứng dụng thông qua domain đã cài đặt với Nginx bằng cách mở file
    #!/bin/bash
    #
    # chkconfig:            2345 70 30
    # description:          Sample app Unicorn
    # processname:          unicorn
    #
    ### BEGIN INIT INFO
    # Provides:             unicorn
    # Required-Start:       $remote_fs $syslog
    # Required-Stop:        $remote_fs $syslog
    # Default-Start:        2 3 4 5
    # Default-Stop:         0 1 6
    # Short-Description:    Start Rails app at boot time
    # Description:          Enable Rails app running by Unicorn daemon
    ### END INIT INFO
    
    7 và thêm dòng sau:

    # /etc/hosts
    127.0.0.1   sample-app.local
    

Sau khi hoàn thành, bạn có thể thử truy cập vào địa chỉ //sample-app.local. Nếu kết quả như bên dưới là bạn đã thành công

Tạm thời bạn chưa cần quan tâm đến lỗi xuất hiện nhé. Vì chúng ta chưa khởi động Unicorn. Vậy là đã xong phần chuẩn bị nguyên liệu, giờ chúng ta bắt tay vào viết service nào.

Viết script

Bây giờ chúng ta đi vào chi tiết viết một init script đơn giản nhé. Việc đầu tiên chúng ta cần làm là tạo một file có thể thực thi [executable] trong thư mục

#!/bin/bash
#
# chkconfig:            2345 70 30
# description:          Sample app Unicorn
# processname:          unicorn
#
### BEGIN INIT INFO
# Provides:             unicorn
# Required-Start:       $remote_fs $syslog
# Required-Stop:        $remote_fs $syslog
# Default-Start:        2 3 4 5
# Default-Stop:         0 1 6
# Short-Description:    Start Rails app at boot time
# Description:          Enable Rails app running by Unicorn daemon
### END INIT INFO
9, mình lấy tên là
set -e
0 cho nó nhanh gọn

  • set -e
    
    1

Tiếp đến, chúng ta thêm đoạn header cho file script với nội dung sau:

#!/bin/bash
#
# chkconfig:            2345 70 30
# description:          Sample app Unicorn
# processname:          unicorn
#
### BEGIN INIT INFO
# Provides:             unicorn
# Required-Start:       $remote_fs $syslog
# Required-Stop:        $remote_fs $syslog
# Default-Start:        2 3 4 5
# Default-Stop:         0 1 6
# Short-Description:    Start Rails app at boot time
# Description:          Enable Rails app running by Unicorn daemon
### END INIT INFO

Mình sẽ giải thích về các keywords trên:

  • CentOS keywords:
    • set -e
      
      2: 2345 là run-levels, 70 là độ ưu tiên khi khởi động, còn 30 là độ ưu tiên khi dừng [các bạn có thể đọc thêm tại đây]. Keyword này để sử dụng cho
      set -e
      
      2 của CentOS.2345 là run-levels, 70 là độ ưu tiên khi khởi động, còn 30 là độ ưu tiên khi dừng [các bạn có thể đọc thêm tại đây]. Keyword này để sử dụng cho
      set -e
      
      2 của CentOS.
    • set -e
      
      4: Mô tả cho init script
    • set -e
      
      5: Tên init script
  • Debian keywords:
    • set -e
      
      6: Chúng ta có thể tạm hiểu là tên khi init script được chạy. Nó phải là duy nhất [unique]
    • set -e
      
      7: Yêu cầu phải có các thành phần được yêu cầu trước khi chạy script. Các bạn có thể đọc thêm tại đâytại đây
    • set -e
      
      8: Giống
      set -e
      
      7, nhưng dành cho lúc dừng script
    • USER=
      APP_NAME="Sample App"
      APP_ROOT=""
      PID_FILE="$APP_ROOT/tmp/pids/unicorn.pid"
      APP_ENV="development"
      CD_CMD="cd $APP_ROOT && [export RAILS_ENV=\"$APP_ENV\";"
      BUNDLER_CMD=" default do bundle exec"
      # BUNDLER_CMD=" exec"
      
      0: Là run-levels của script khi chạy. Giống tham số đầu tiên của keyword
      set -e
      
      2
    • USER=
      APP_NAME="Sample App"
      APP_ROOT=""
      PID_FILE="$APP_ROOT/tmp/pids/unicorn.pid"
      APP_ENV="development"
      CD_CMD="cd $APP_ROOT && [export RAILS_ENV=\"$APP_ENV\";"
      BUNDLER_CMD=" default do bundle exec"
      # BUNDLER_CMD=" exec"
      
      2: Giống
      USER=
      APP_NAME="Sample App"
      APP_ROOT=""
      PID_FILE="$APP_ROOT/tmp/pids/unicorn.pid"
      APP_ENV="development"
      CD_CMD="cd $APP_ROOT && [export RAILS_ENV=\"$APP_ENV\";"
      BUNDLER_CMD=" default do bundle exec"
      # BUNDLER_CMD=" exec"
      
      0, nhưng dành cho lúc dừng script.
    • USER=
      APP_NAME="Sample App"
      APP_ROOT=""
      PID_FILE="$APP_ROOT/tmp/pids/unicorn.pid"
      APP_ENV="development"
      CD_CMD="cd $APP_ROOT && [export RAILS_ENV=\"$APP_ENV\";"
      BUNDLER_CMD=" default do bundle exec"
      # BUNDLER_CMD=" exec"
      
      4: Mô tả ngắn gọn cho script
    • USER=
      APP_NAME="Sample App"
      APP_ROOT=""
      PID_FILE="$APP_ROOT/tmp/pids/unicorn.pid"
      APP_ENV="development"
      CD_CMD="cd $APP_ROOT && [export RAILS_ENV=\"$APP_ENV\";"
      BUNDLER_CMD=" default do bundle exec"
      # BUNDLER_CMD=" exec"
      
      5: Mô tả đầy đủ cho script

Vậy là đã xong phần header của script. Bây giờ chúng ta tiếp tục viết nhé. Tiếp theo, bạn thêm dòng sau:

set -e

Theo như man page của Ubuntu thì lệnh

USER=
APP_NAME="Sample App"
APP_ROOT=""
PID_FILE="$APP_ROOT/tmp/pids/unicorn.pid"
APP_ENV="development"
CD_CMD="cd $APP_ROOT && [export RAILS_ENV=\"$APP_ENV\";"
BUNDLER_CMD=" default do bundle exec"
# BUNDLER_CMD=" exec"
6 giúp chúng ta đặt hoặc bỏ chọn giá trị các tùy chọn của shell. Tham số
USER=
APP_NAME="Sample App"
APP_ROOT=""
PID_FILE="$APP_ROOT/tmp/pids/unicorn.pid"
APP_ENV="development"
CD_CMD="cd $APP_ROOT && [export RAILS_ENV=\"$APP_ENV\";"
BUNDLER_CMD=" default do bundle exec"
# BUNDLER_CMD=" exec"
7 có ý nghĩa là thoát ngay lập tức nếu một câu lệnh nào đó trả ra một exit code khác 0. Tiếp, chúng ta đi khai báo một số biến sẽ dùng trong script:

USER=
APP_NAME="Sample App"
APP_ROOT=""
PID_FILE="$APP_ROOT/tmp/pids/unicorn.pid"
APP_ENV="development"
CD_CMD="cd $APP_ROOT && [export RAILS_ENV=\"$APP_ENV\";"
BUNDLER_CMD=" default do bundle exec"
# BUNDLER_CMD=" exec"

Sau đây là chi tiết các biến được khai báo:

  • USER=
    APP_NAME="Sample App"
    APP_ROOT=""
    PID_FILE="$APP_ROOT/tmp/pids/unicorn.pid"
    APP_ENV="development"
    CD_CMD="cd $APP_ROOT && [export RAILS_ENV=\"$APP_ENV\";"
    BUNDLER_CMD=" default do bundle exec"
    # BUNDLER_CMD=" exec"
    
    8: Là user bạn sẽ chạy lệnh. Trên server bạn thường chạy Unicorn ở user khác
    USER=
    APP_NAME="Sample App"
    APP_ROOT=""
    PID_FILE="$APP_ROOT/tmp/pids/unicorn.pid"
    APP_ENV="development"
    CD_CMD="cd $APP_ROOT && [export RAILS_ENV=\"$APP_ENV\";"
    BUNDLER_CMD=" default do bundle exec"
    # BUNDLER_CMD=" exec"
    
    9 [như
    get_pid[] {
      cat "$PID_FILE"
    }
    
    is_running[] {
      [ -f "$PID_FILE" ] && kill -0 $[get_pid] > /dev/null 2>&1
    }
    
    0 chả hạn]. Còn đây là chúng ta đang chạy ở local nên bạn thay bằng user hiện tại cho phù hợp. Bạn có thể thực hiện lệnh
    get_pid[] {
      cat "$PID_FILE"
    }
    
    is_running[] {
      [ -f "$PID_FILE" ] && kill -0 $[get_pid] > /dev/null 2>&1
    }
    
    1 để xem.
  • get_pid[] {
      cat "$PID_FILE"
    }
    
    is_running[] {
      [ -f "$PID_FILE" ] && kill -0 $[get_pid] > /dev/null 2>&1
    }
    
    2: Đơn giản chỉ sử dụng cho phần hiển thị ở phía sau
  • get_pid[] {
      cat "$PID_FILE"
    }
    
    is_running[] {
      [ -f "$PID_FILE" ] && kill -0 $[get_pid] > /dev/null 2>&1
    }
    
    3: Đường dẫn đến thư mục của project
  • get_pid[] {
      cat "$PID_FILE"
    }
    
    is_running[] {
      [ -f "$PID_FILE" ] && kill -0 $[get_pid] > /dev/null 2>&1
    }
    
    4: Đường dẫn đến file chứa process ID của Unicorn
  • get_pid[] {
      cat "$PID_FILE"
    }
    
    is_running[] {
      [ -f "$PID_FILE" ] && kill -0 $[get_pid] > /dev/null 2>&1
    }
    
    5: Môi trường khi chạy Rails app. Bạn có thể thay đổi nó cho phù hợp
  • get_pid[] {
      cat "$PID_FILE"
    }
    
    is_running[] {
      [ -f "$PID_FILE" ] && kill -0 $[get_pid] > /dev/null 2>&1
    }
    
    6: String chứa lệnh start Unicorn trong thư mục project
  • get_pid[] {
      cat "$PID_FILE"
    }
    
    is_running[] {
      [ -f "$PID_FILE" ] && kill -0 $[get_pid] > /dev/null 2>&1
    }
    
    7: Thực hiện chạy Unicorn bằng
    get_pid[] {
      cat "$PID_FILE"
    }
    
    is_running[] {
      [ -f "$PID_FILE" ] && kill -0 $[get_pid] > /dev/null 2>&1
    }
    
    8. Bạn có thể sử dụng một trong hai và sửa lại đường dẫn cho phù hợp. Nếu bạn dùng RVM thì nên dùng cái đầu tiên. Bạn có thể chạy lệnh
    get_pid[] {
      cat "$PID_FILE"
    }
    
    is_running[] {
      [ -f "$PID_FILE" ] && kill -0 $[get_pid] > /dev/null 2>&1
    }
    
    9 hoặc
    case "$1" in
      start]
        do_start
        ;;
      stop]
        do_stop
        ;;
      restart]
        do_restart
        ;;
      status]
        do_status
        ;;
      reload]
        do_reload
        ;;
      *]
        echo "Usage: $0 {start|stop|restart|reload|status}"
        ;;
    esac
    
    0 để lấy đường dẫn đến file thực thi của RVM hoặc Bundler.

Tiếp, chúng ta đi viết hai function là lấy PID hiện tại của Unicorn và kiểm tra xem nó có chạy không để sử dụng cho các function như start, stop, restart, status, reload:start, stop, restart, status, reload:

get_pid[] {
  cat "$PID_FILE"
}

is_running[] {
  [ -f "$PID_FILE" ] && kill -0 $[get_pid] > /dev/null 2>&1
}

Trong hai function trên. Function

case "$1" in
  start]
    do_start
    ;;
  stop]
    do_stop
    ;;
  restart]
    do_restart
    ;;
  status]
    do_status
    ;;
  reload]
    do_reload
    ;;
  *]
    echo "Usage: $0 {start|stop|restart|reload|status}"
    ;;
esac
1 thì không có gì đặc biệt ngoài việc đọc file PID. Còn function
case "$1" in
  start]
    do_start
    ;;
  stop]
    do_stop
    ;;
  restart]
    do_restart
    ;;
  status]
    do_status
    ;;
  reload]
    do_reload
    ;;
  *]
    echo "Usage: $0 {start|stop|restart|reload|status}"
    ;;
esac
2 thì có một lệnh khá lạ là
case "$1" in
  start]
    do_start
    ;;
  stop]
    do_stop
    ;;
  restart]
    do_restart
    ;;
  status]
    do_status
    ;;
  reload]
    do_reload
    ;;
  *]
    echo "Usage: $0 {start|stop|restart|reload|status}"
    ;;
esac
3. Với signal 0 có nghĩa là lệnh kill này không gửi signal tới process đó nhưng nó vẫn kiểm tra xem có lỗi khi kill hay không. Chúng ta sử dụng nó để kiểm tra xem Unicorn có đang chạy hay không. Còn đoạn
case "$1" in
  start]
    do_start
    ;;
  stop]
    do_stop
    ;;
  restart]
    do_restart
    ;;
  status]
    do_status
    ;;
  reload]
    do_reload
    ;;
  *]
    echo "Usage: $0 {start|stop|restart|reload|status}"
    ;;
esac
4 đơn giản chỉ là không hiển thị
case "$1" in
  start]
    do_start
    ;;
  stop]
    do_stop
    ;;
  restart]
    do_restart
    ;;
  status]
    do_status
    ;;
  reload]
    do_reload
    ;;
  *]
    echo "Usage: $0 {start|stop|restart|reload|status}"
    ;;
esac
5 và
case "$1" in
  start]
    do_start
    ;;
  stop]
    do_stop
    ;;
  restart]
    do_restart
    ;;
  status]
    do_status
    ;;
  reload]
    do_reload
    ;;
  *]
    echo "Usage: $0 {start|stop|restart|reload|status}"
    ;;
esac
6 [trong trường hợp PID đó không tồn tại]. Đưa tất cả về lỗ đen
case "$1" in
  start]
    do_start
    ;;
  stop]
    do_stop
    ;;
  restart]
    do_restart
    ;;
  status]
    do_status
    ;;
  reload]
    do_reload
    ;;
  *]
    echo "Usage: $0 {start|stop|restart|reload|status}"
    ;;
esac
7 . Okay, tiếp theo chúng ta đi viết script xử lý các tham số nhận vào khi chạy service nhé. Tại sao lại viết từ đoạn này? Là mình muốn để mọi người viết function nào thì có thể test luôn function đó. Đoạn code này nó phải ở cuối. Dưới các function sẽ được khai báo tiếp theo nhé:
. Okay, tiếp theo chúng ta đi viết script xử lý các tham số nhận vào khi chạy service nhé. Tại sao lại viết từ đoạn này? Là mình muốn để mọi người viết function nào thì có thể test luôn function đó. Đoạn code này nó phải ở cuối. Dưới các function sẽ được khai báo tiếp theo nhé:

case "$1" in
  start]
    do_start
    ;;
  stop]
    do_stop
    ;;
  restart]
    do_restart
    ;;
  status]
    do_status
    ;;
  reload]
    do_reload
    ;;
  *]
    echo "Usage: $0 {start|stop|restart|reload|status}"
    ;;
esac

Trong khối lệnh

case "$1" in
  start]
    do_start
    ;;
  stop]
    do_stop
    ;;
  restart]
    do_restart
    ;;
  status]
    do_status
    ;;
  reload]
    do_reload
    ;;
  *]
    echo "Usage: $0 {start|stop|restart|reload|status}"
    ;;
esac
8 ở trên không có gì đặc biệt ngoài đọc tham số đầu tiên [là
case "$1" in
  start]
    do_start
    ;;
  stop]
    do_stop
    ;;
  restart]
    do_restart
    ;;
  status]
    do_status
    ;;
  reload]
    do_reload
    ;;
  *]
    echo "Usage: $0 {start|stop|restart|reload|status}"
    ;;
esac
9] rồi gọi function tương ứng. Nếu
case "$1" in
  start]
    do_start
    ;;
  stop]
    do_stop
    ;;
  restart]
    do_restart
    ;;
  status]
    do_status
    ;;
  reload]
    do_reload
    ;;
  *]
    echo "Usage: $0 {start|stop|restart|reload|status}"
    ;;
esac
9 không nằm trong các case được định nghĩa thì in thông báo hướng dẫn sử dụng. Tiếp, chúng ta đi viết function kiểm tra trạng thái của Unicorn có đang chạy hay không:

do_status[] {
  if is_running; then
    echo "$APP_NAME [process $[get_pid]] is running..."
  else
    echo "$APP_NAME is stopped"
  fi
}

Trong function trên không có gì đặc biệt cần phải giải thích. Bây giờ bạn thử thực thi lệnh

do_status[] {
  if is_running; then
    echo "$APP_NAME [process $[get_pid]] is running..."
  else
    echo "$APP_NAME is stopped"
  fi
}
1 hoặc
do_status[] {
  if is_running; then
    echo "$APP_NAME [process $[get_pid]] is running..."
  else
    echo "$APP_NAME is stopped"
  fi
}
2 để xem kết quả ra sao ! Giờ chúng ta đi viết lần lượt các function còn lại nhé. Đầu tiên là
do_status[] {
  if is_running; then
    echo "$APP_NAME [process $[get_pid]] is running..."
  else
    echo "$APP_NAME is stopped"
  fi
}
3.
! Giờ chúng ta đi viết lần lượt các function còn lại nhé. Đầu tiên là
do_status[] {
  if is_running; then
    echo "$APP_NAME [process $[get_pid]] is running..."
  else
    echo "$APP_NAME is stopped"
  fi
}
3.

do_start[] {
  if is_running; then
    echo "$APP_NAME already started"
  else
    echo "Starting $APP_NAME..."
    su - $USER -c "$CD_CMD $BUNDLER_CMD unicorn -c $APP_ROOT/config/unicorn/$APP_ENV.rb -E $APP_ENV -D]"
    sleep 5
    echo "$APP_NAME started with process $[get_pid]"
  fi
}

Cũng không có gì đặc biệt ở function

do_status[] {
  if is_running; then
    echo "$APP_NAME [process $[get_pid]] is running..."
  else
    echo "$APP_NAME is stopped"
  fi
}
4 này. Đơn giản chỉ là kiểm tra nếu Unicorn đang chạy thì hiển thị thông báo. Còn không thì start Unicorn và đợi 5s [thời gian tương đối để đợi Unicorn được khởi động - đôi khi cũng hên xui ]. Giờ bạn có thể thử hai lệnh start và status để xem kết quả:
]. Giờ bạn có thể thử hai lệnh start và status để xem kết quả:

$ sudo service unicorn status
Sample App is stopped
$ sudo service unicorn start
Starting Sample App...
Sample App started with process 10500
$ sudo service unicorn status
Sample App [process 10500] is running...
$ ps ax | grep "[u]nicorn master"
10500 ?        Sl     0:01 unicorn master -c /config/unicorn/development.rb -E development -D

Đã có start, bây giờ chúng ta sang phần stop:

# /etc/hosts
127.0.0.1   sample-app.local
0

Ở function

do_status[] {
  if is_running; then
    echo "$APP_NAME [process $[get_pid]] is running..."
  else
    echo "$APP_NAME is stopped"
  fi
}
5 này. Chúng ta sẽ kiểm tra xem, nếu Unicorn đang chạy thì thực hiện kill nó với signal QUIT và đợi 5s [cũng vẫn là con số tương đối ] rồi kiểm tra lại xem nó đã thực sự được stop hay chưa. Bây giờ bạn có thể thử lệnh stop [sau khi đã thử lệnh start ở trên] rồi tiếp lệnh status xem sao
] rồi kiểm tra lại xem nó đã thực sự được stop hay chưa. Bây giờ bạn có thể thử lệnh stop [sau khi đã thử lệnh start ở trên] rồi tiếp lệnh status xem sao

# /etc/hosts
127.0.0.1   sample-app.local
1

Xong phần stop. Chúng ta sang phần restart. Phần này là đơn giản nhất. Chỉ cần kiểm tra xem Unicorn có chạy hay không. Nếu đang chạy rồi thì stop nó và start lại. Nếu chưa chạy thì start nó lên:

# /etc/hosts
127.0.0.1   sample-app.local
2

Bây giờ, bạn thử thực hiện việc restart xem nó đã chạy đúng chưa. Dưới đây là test case của mình:

# /etc/hosts
127.0.0.1   sample-app.local
3

Vậy là xong phần restart. Với ứng dụng khác thì có thể là đã đủ, nhưng với Unicorn thì vẫn chưa đủ. Vì Unicorn nó có hỗ trợ gửi signal reload lại process [Unicorn signal handling] để nhận code mới mà không gây gián đoạn đến việc truy cập vào trang của người dùng [bạn có thể xem thêm bài Zero downtime deployment for Rails with Capistrano and Unicorn để hiểu hơn] nên chúng ta thêm lệnh reload [nếu bạn thấy cần] nhé. Function

do_status[] {
  if is_running; then
    echo "$APP_NAME [process $[get_pid]] is running..."
  else
    echo "$APP_NAME is stopped"
  fi
}
6 này đơn giản chỉ là kiểm tra xem Unicorn có đang chạy hay không. Nếu đang chạy thì gửi signal
do_status[] {
  if is_running; then
    echo "$APP_NAME [process $[get_pid]] is running..."
  else
    echo "$APP_NAME is stopped"
  fi
}
7 tới master PID là xong.Zero downtime deployment for Rails with Capistrano and Unicorn để hiểu hơn] nên chúng ta thêm lệnh reload [nếu bạn thấy cần] nhé. Function
do_status[] {
  if is_running; then
    echo "$APP_NAME [process $[get_pid]] is running..."
  else
    echo "$APP_NAME is stopped"
  fi
}
6 này đơn giản chỉ là kiểm tra xem Unicorn có đang chạy hay không. Nếu đang chạy thì gửi signal
do_status[] {
  if is_running; then
    echo "$APP_NAME [process $[get_pid]] is running..."
  else
    echo "$APP_NAME is stopped"
  fi
}
7 tới master PID là xong.

# /etc/hosts
127.0.0.1   sample-app.local
4

Xong phần reload. Bạn có thể kiểm tra theo test case sau của mình:

# /etc/hosts
127.0.0.1   sample-app.local
5

Misson completed !

!

Lời kết

Đến đây, bài viết chia sẻ làm sao để viết được một Linux init script đơn giản đã kết thúc. Hy vọng hai bài viết là bài này và bài Managing services with update-rc.d sẽ giúp ích cho mọi người trong một thời điểm nào đó. Service này mình viết vẫn còn non tay [do phải mày mò và tổng hợp rất nhiều cách viết mà mình đã tìm kiếm trên mạng] nên có gì thiếu sót mong mọi người thông cảm và góp ý ở phần bình luận nhé. Chào thân ái và quyết thắng !Managing services with update-rc.d sẽ giúp ích cho mọi người trong một thời điểm nào đó. Service này mình viết vẫn còn non tay [do phải mày mò và tổng hợp rất nhiều cách viết mà mình đã tìm kiếm trên mạng] nên có gì thiếu sót mong mọi người thông cảm và góp ý ở phần bình luận nhé. Chào thân ái và quyết thắng

!

Original post: //namnv609.cf/posts/write-linux-init-script.html

Bài Viết Liên Quan

Chủ Đề