Các Lược Giảng Chuyên Sâu về Sử Dụng Văn Lệnh BASH trong Linux

Vietsciences-Làng Đậu      29/11/2006

Những bài cùng tác giả

Loạt bài " Các Lược Giảng Chuyên Sâu về Sử Dụng Văn Lệnh BASH trong Linux" của tác giả Làng Đậu giữ bản quyền 2006. Người đọc chỉ được sử dụng cho mục đích học tập hay giảng dạy cho cá nhân. Cấm mọi hình thức sao chép hay in lại nhằm mục đích mua bán hay trục lợi mà không có sự đồng ý chính thức của tác giả.  Mọi thông tin về việc phổ biến rộng rãi có tính quảng bá tài liệu này cho mục đích giáo dục xin liên lạc về vo_quang_nhan@yahoo.com  

 

Bài 4:

14 Các biến môi trường

Biến môi trường là biến toàn cục thường đã được định nghiã từ trước giá trị của nó.  Khi viết các văn lệnh bạn nên tránh dùng các tên biến trùng với tên đã được định nghiã bởi BASH. Để hiển thị tên và giá trị hiện tại của một số biến môi trường có thể dùng lệnh env . Số khác có thể không có mặt trong nội dung của $env hay chưa đuợc định nghiã.  Trong trường hợp biến đã được xác định thì có thể dùng  cú pháp:

echo $<TÊN_BIẾN> để hiển thị nội dung  (chẳng hạn như lệnh echo $PS1 sẽ cho giá trị cài đặt của biến môi trường PS1)

Các biến môi trường này có thể thường trực tồn tại hoặc chỉ tồn tại trong điều kiện nào đó (như là chỉ có khi chạy một văn lệnh chẳng hạn). Giá trị của các biến môi trường quan trọng là:

14.1 $BASH đường dẫn của tập tin trình dịch BASH (thường là /bin/bash )

14.2 $GROUPS nhóm người dùng

14.3 $HOME Thư mục truy cập của người dùng, thưuờng được viết tắt là ~ (xem tham số mở rộng trong BASH)

14.4 $HOSTNAME tên của hệ thống (máy chủ)

14.5 $HOSTTYPE hệ thống phần cứng

14.6 $IFS Biến ngăn cách-- BASH lưu giá trị mặc định của kí tự ngăn cách giữa các miền (field) thường dùng trong các vòng lặp.(xem bài 3)

14.7 $MACHTYPE Kiểu hệ thống (cpu-company-system )

Thí dụ:

$echo "$MACHTYPE"
$i686-pc-linux-gnu

14.8 $OLDPWD tên thư mục hiện hoạt trước đây (tên cuối cùng trước khi thư mục hiện hoạt bị thay đổi). Khi mới dăng nhập thì biến này không tồn tại.  Nhưng một khi người dùng đang ở thư mục A và chuyển thư mục hiện hoạt sang bất kì thư mục B nào khác thì $OLDPWD sẽ được tạo ra bởi BASH và có giá trị là A. (xem thêm $PWD ở 14.11)

14.9 $OSTYPE tên bản nền (platform)

14.10 $PATH nội dung bao gồm các đường dẫn để BASH tự động tìm đên và thi hành một khi có các mệnh lệnh được gọi mà không có cung cấp tên đầy đủ

14.11 $PWD tên thư mục hiện hoạt. Khi di chuyển sang thư mục khác (bằng lệnh cd chẳng hạn) thì giá trị cũ sẽ được gán cho $OLDPWD , còn giá trị của thư mục vừa chuyển tới được cập nhật vào $PWD (xem thêm $OLDPWD ở 14.8)

14.12 $PPID ID của tiến trình của chương trình cha mẹ đang chạy  (Trong một văn lệnh đang chạy thì $PPID là số tiến trình của BASH đang dùng để chạy văn lệnh đó)

14.13 $RANDOM   Biến này sẽ chứa một giá trị ngẫu nhiên khác nhau mỗi lần nó được truy cập. Số ngẫu nhiên này là số nguyên từ 0 tới 23767 (thực chất đây là một số giả ngẫu nhiên (pseudo-randomize number) is an integer in rang 0..32767

Thí dụ:

MyNum1="$RANDOM"
MyNum2="$RANDOM"
echo "the values are $MyNum1 $MyNum2"

14.14 $SECONDS số thời gian tính bằng giây mà văn lệnh đã chạy

14.15 $UID ID của người dùng

14.16 $CPU CPU trên máy

14.17 $LOGNAME:  Tên người dăng nhập

14.18 $USER: Tên người dùng

14.19 $SHELL: tên đầy đủ của trình bao gán cho người dùng

14.20 $PS1   Dòng hiển thị của dấu nhắc (prompt) sơ cấp. Giá trị của  biến này sẽ quy định cách thức và nội dung hiển thị.   Thí dụ:  SuSE SLES 9 có thể cài mặc định dòng nhắc là h:w # Tức là nó sẽ cho ra dòng như là <Tên_máy_chủ>:<Tên_thư_mục_hiện_hoạt> #.   Bạn có thể cài đặt lại dòng hiển thị này bằng cách gán giá trị mới cho IPSThí dụ: để dòng hiển thị báo ngày hiện tại và thư mục hiện hoạt thì có thể dùng lệnh IPS="\d-\w #"

\d ngày tháng
\D{
<định_dạng>}
  Dòng  strftime(3) sẽ đưa gian hiện tại vào; nếu  <định_dạng> không có thì sẽ hiện thị theo cách cài đặt thời gian theo địa phương . Dấu ngoặc { } phải có mặt để BASH hiểu tham số này  (Xem thêm chi tiết về cách định dạng dòng thời gian xuất ra bởi lệnh man 3 strftime ). sau đây là một số giá trị có thể dùng của PS1
\e
Kí tự thoát.
\h
Tên máy chủ (hostname) cho đến dấu chấm . đầu tiên.
\H
Tên máy chủ.
\l Tên của thiết bị đầu cuối chạy trình bao
\n Kí tự đầu dòng.
\r Kí tự xuống hàng.
\s Tên của văn lệnh (giá trị tên không đầy đủ của $0)
\t Thời gian, kiểu 24-giờ dạng HH:MM:SS.
\T Thời gian, kiểu 12-giờ dạng HH:MM:SSt.
\@ Thời gian, kiểu 12-giờ dạng am/pm.
\A Thời gian, kiểu 24-giờ dạng  HH:MM.
\u Tên tài khoảng của người đang dùng.
\v Số phiên bản của Bash
\V Số phiên bản phát hành của Bash, version + patchlevel (e.g., 2.00.0)
\w Tên thư mục hiện hoạt.
\W Tên không đầy đủ của $PWD.
\! Sử số (history number) của lệnh này.
\# Lệnh số (command number) của lệnh này.
\nnn Kí tự trong mã ASCII mà giá trị bát phân là nnn.
\\ Dấu nghiên về (backslash)
\[   Kí tự mở đầu của một dãy kí tự không in được (non-printing character). Có thể dùng để nhúng (embed) dãy điều khiển đầu cuối vào trong dòng nhắc (prompt string).
\] Kí tự kết thúc của một dãy kí tự không in được

14.21 $PS2 Dòng nhắc thứ cấp. Gíá trị mặc định là  > .  Biến này thường thấy hiển thị trên thiết bị đầu cuối mỗi khi người dùng gõ xong dòng lệnh nhưng vẩn chưa kết thúc đầy đủ.  Thí dụ nếu người dùng gõ lệnh myvar=test; echo "myvar   (thiếu một dấu ngoặc kép) thì BASH sẽ hiển thị dòng nhắc thứ cấp. (tức là dấu  > ) để kết thúc người dùng có thể gõ thêm dấu " hay kết thúc lệnh đó bằng tổ hợp phím <Ctrl>+<c>

14.23 $BASH_VERSION Số phiên bản đầy đủ của thực thể BASH.

14.24 BASH_VERSINFO  là mảng các hằng lưu giữ thông tin về phiên bản của thực thể BASH các giá trị bao gồm:

$BASH_VERSINFO[0] Chính số của phiên bản  (bản phát hành).
$BASH_VERSINFO[1] Phụ số của phiên bản (bản phát hành).
$BASH_VERSINFO[2] Cấp che vá.
$BASH_VERSINFO[3] Phiên bản dựng (build version)
$BASH_VERSINFO[4] Tình Trạng phát hành  (thí dụ  beta1).
$BASH_VERSINFO[5] Giá tri- của biến MACHTYPE.

14.25 $FUNCNAME Tên của hàm đang được thi hành bên trong trình bao. Biến này chỉ tồn tại trong khi một hàm đang được thực thi. Không thể gán giá trị mới cho nó (sẽ nhận về trạng thái lỗi)

14.26 $LINENO Số thứ tự của dòng hiện tại trong văn lệnh hay của hàm (của trình bao) đang được thực thi

14.27 $PROMPT_COMMAND Nếu được cài thì giá trị của biến này sẽ được hiểu như là một mệnh lệnh để thi hành trước khi hiển thị  dòng nhắc sơ cấp  ($PS1).

14.28 $PS3  giá trị của biến này chỉ dùng trong việc hiển thị của lệnh select. Giá trị mặc định là #?

14.29 $SHLVL Sẽ tăng 1 đơn vị mỗi lần có một thực thể của BASH được bắt đầu. Biến này chủ ý được dùng để tính độ sâu như thế nào mà các trình bao BASH lồng nhau.

14.30  $TMOUT Nếu được cài giá trị lớn hơn 0 thì, TMOUT sẽ trở thành thời gian hết hạn mặc định cho việc đọc (từ console chẳng hạn).
Lệnh select sẽ kết thúc nếu nó không nhận đưọc dữ liệu nhập từ thiết bị đầu cuối sau khoảng thời gian $TMOUT giây.
Trong các hệ vỏ tương tác, gía trị này là số giây để đợi dữ liệu nhập sau một lệnh dòng nhắc. BASH sẽ ngừng sau số giây $TMUOT nếu mà dữ liệu nhập chưa đến. 15 Tham số đặc biệt quan trọng (phân biệt với lệnh dạng kí tự)

Các tham số đặc biệt này chỉ được dùng để đọc giá trị  và BASH không cho phép gán giá trị lên chúng.

15.1 0, 1, 2 ,...   các tham số của văn lệnh (hay của hàm) từ vị trí 0, 1, 2...nếu nó được gọi. BASH cung cấp tối da 10 giá tri (từ $0 tới $9). Trong trường hợp gọi một văn lệnh thì $0 là tên của văn lệnh, $1 là giá trị của tham số đầu tiên, $2 là giá trị của tham số thứ nhì,.... Ngoài ra, ngoại trừ giá trị $0 không đổi,  các tên $<n> (n > 0) sẽ nhận giá trị chứa trong $<n+1> sau mỗi lần thi hành lệnh shift. Do đó, nếu gọi giá trị $<max>, trong đó max là tên biến lớn nhất chứa giá trị khác null, sau mỗi lệnh shift sẽ chưá giá trị null (vì giá trị khác null của nó đã chuyển cho $<max-1>

Thí dụ:

#the affect of 'shift' on $1, $2, $3,...
#!/bin/bash
# file name: ShiftTest
echo "the values of parameters are: $0, $1, $2, $3, $4, and $5"
shift
echo "after calling shift, their values become: $0, $1, $2, $3, and $4"

After saving under the name ShiftTest, issue commands:
#chmod 755 ./ShiftTest
#./ShiftTest one two three four five

The Scipt will display as
#the values of paramaters are: one, two, three, four, and five
#after calling shift their values become: two, three, four, and five

15.2 # biến này chứa tổng số tham số có giá trị khác null khi văn lệnh được gọi.

15.3 ? Biến chứa mã thoát của mệnh lệnh cuối cùng trong văn lệnh trả về (giá trị này thường là 0 nếu mệnh lệnh thi hành thành công)

Thí dụ:

echo "bash location :$BASH"
echo "number of argument when calling this script :$#"
if [ ! $# -eq 2 ]; then                   # if there are not 2 arguments then
      echo "too many parameters given"    #display error
      exit 1                              #Exit code = 1
else
      echo "now we copy file $1 to $2"
      cp -f $1 $2 1>/dev/null 2>/dev/null #copy file but suppress output messages
      if [ $? = 0 ]; then
             echo "copied."
      else
            echo "error while copying with the error code $?"
     fi
fi

15.4 *  Cho danh sách các tham số vị trí, bắt đầu từ  vị trí 1. Như vậy $* sẽ là danh sác các tham số được ngăn cách nhau bởi dấu ngăn cách $IFS. Nếu để cài đặt mặc định thì $* tương đương với string "$1 $2 $3 ...$n"   (với $n là tham số cuối cùng khác null)

15.5 @  Nội dung của $@ sẽ là danh sách các tham số vị trí, bắt đầu từ  vị trí 1. Tuy nhiên, danh sách đó có dạng  "$1" "$2" ... ."$n". Khi không có tham số $@ có giá trị null.

15.6 $   Cung cấp ID của tiến trình của trình bao. Trong  một  trình bao con ( )  , $$   là ID của tiến trình của trình bao gọi không phải của trình bao con

15.7 !   Nội dung là tiến trình ID của lệnh sau cùng được thực thi trong nền (một cách không đồng bộ).

16 Quy ước về sử dụng dấu ngã ~ (tilde)

Trong BASH dấu ~ mang ý nghiã đặc biệt. tùy theo các kí tự nối theo sau nó.

~    Giá trị của $HOME.  Thí dụ: ~/mydir  tương đương với thư mục $HOME/mydir

~ <Tên_tài_khoản>/ Trả về tên thư mục nhà (home directory) của <Tên_tài_khoản>

~+   Tương đương với  gía trị $PWD

~-   Tương đương với  gía trị  $OLDPWD

16 Hàm

Giống như C/C++Linux, BASH xem thủ tục cũng là mộtdạng hàm không có tham số. Cú pháp của một hàm thường là một trong các dạng

  • function <TÊN_HÀM> {
        
    <KHỐI_LỆNH>

    }
  • <TÊN_HÀM> () {
        
    <KHỐI_LỆNH>
    }
  • <TÊN_HÀM> ()

        
    <KHỐI_LỆNH>
    }

16.1 Đặc điểm chung của hàm trong BASH

  1. Khi thưc thi một văn lệnh, có thể có trường hợp các mệnh lệnh, các lệnh nội tại, các tên thay thế (chẳng hạn như các tên làm ra từ lệnh  alias ) và các hàm có cùng tên, thì BASH sẽ ưu tiên tìm tới tên thay thế trước, sau đó là tên hàm, và sau cùng mới tìm kiếm trong các mệnh lệnh theo thứ tự này.  Do đó, nên tránh đặt tên các hàm trùng với các tên thay thế. Ngoài ra, khi gọi các mệnh lệnh có cùng tên với hàm trong văn lệnh thì tốt nhất là dùng tên đầy đủ của mệnh lệnh đó
  2. Hàm phải được định nghiã trước khi nó được sử dụng
  3. Các biến thông thường của một hàm được chia sẽ chung trong một văn lệnh. Tuy nhiên, một biến địa phương có thể được tạo ra bởi từ khoá local
    (
    Thí dụ như local local_var=10)
  4. Nếu sử dụng câu lệnh return trong một hàm thì nó sẽ lập tức trả dòng điều khiển về cho dòng điều khiển chính của văn lệnh và giá trị trả về (return) chính là giá trị thoát (exit status) mệnh lệnh cuối cùng mà hàm đó thực thi.  Để chỉ thị một giá trị xác định khi trả về thì người ta dùng cú pháp  return <n> (chẳng hạn như return 2 hay là  return $number)  
  5. Một hàm có thể được xuất cho các trình bao con bằng cách dùng câu lệnh với cú pháp: export -f <TÊN_HÀM>
  6. Các hàm được chứa trong một tập tin khác cùng có thể tải lên văn lệnh hiện hoạt bằng mệnh lệnh:
    .
    <TÊN_TẬP_TIN_HÀM>

    hay là
    source
    <TÊN_HÀM>
    (
    Thí dụ: để sử dụng các hàm có định nghiã trong một tập tin là myFunc , thì người ta có thể tải nó trước bằng các thêm lệnh  . myFunc (hay lệnh source myFunc ) vào trong văn lệnh hiện tại)
  7. BASH hỗ trợ khả năng đệ quy của các hàm
  8. Bên trong một hàm có thể gọi hàm khác. (xem Thí dụ)
  9. Để xóa khỏi bộ nhớ hàm đã được tải từ trước, dùng lệnh có cú pháp: unset -f <TÊN_HÀM>
  10. Để hiển thị lại danh mục các hàm đã định nghiã từ trước dùng declare -f (xem lại bài 2)

Thí dụ1:

#!/bin/bash
#script file name :hello
hello ()   #define this function before calling it
{
    echo "hello world"
    return 0      #optional you may add/remove this line
}

echo "call function hello()"
hello

Thí dụ2: Xuất các hàm sang nơi khác
Nội dung của tập tin file1:
#!bin/bash
#file name file1
#calling the function myfunc in the parent scripts (file2)
echo "calling from the child scripts"
myfunc
exit 0

Nội dung của tập tin file2:
#!/bin/bash
#file name file2
#Exporting function myfunc to all of its childs
myfunc ()
{
      echo "myfunc running"
}
#now call the child script to see what is done
# remember: chmod 755 ./file1
./file1

16.2 Truyền tham số và đọc gía trị trả về từ một hàm

16.2.1 Truyền tham số:  

  • Sử dụng các đối số theo cú pháp:
    <TÊN_HÀM>  <TÊN_BIẾN1>  <TÊN_BIẾN2>  <TÊN_BIẾN3> ...
    Với phương pháp này thì bên trong hàm thì nội dung $<TÊN_BIẾN1> sẽ được gán thành $1 ,  $<TÊN_BIẾN2> sẽ được gán thành $2 ,  và $<TÊN_BIẾN3> sẽ được gán thành $3 ,....(xem thí dụ)
  • Sử dụng việc truyền tham số như là các biến thông thường.  Tất cả các biến được định nghiã trong một văn lệnh sẽ được xem như là biến toàn cục của riêng văn lệnh đó (nếu chúng không được khai báo địa phương) và do đó chúng có thể được truy cập trực tiếp bên trong một hàm của văn lệnh này

16.2.2 đọc giá trị trả về:

  • Tiếp nhận giá trị nguyên trả về bằng lệnh return bên trong hàm (thí dụ2). Trường hợp này giá trị trả về chứa trong tham số đặc biệt #?
  • Tiếp nhận giá trị của các tham số thông qua các biến trong văn lệnh. Các biến trong một tập tin là biến toàn cục đối với tập tin đó, nên chúng có thể được thay đổi giá trị này bên trong hàm và được đọc lại từ bên ngoài hàm
  • Tiếp nhận các giá trị từ ngỏ ra của hàm. Trong trường hợp này hàm có thể dùng lệnh echo để xuất giá trị. (thí dụ3) Việc gọi hàm  và giá trị tiếp nhận giá trị trả ra thông qua cú pháp :
    $(<TÊN_HÀM>
    <TÊN_BIẾN1>  <TÊN_BIẾN2>  <TÊN_BIẾN3> ...)

16.2.3 Thí dụ: Các thí dụ mô phỏng từ mã có trong các nguồn mở nêu ở tài liệu tham khảo

Thí dụ1:  Truyền tham số bằng các biến thông thường

#!/bin/bash
myfunc ()
{
    echo " data passing before:  data=$dat, number=$num"
    data="new value"
   num=0
}
#now declaring variables
dat="orig value"
num=12

Thí dụ2: Nhận giá trị trả ra từ hàm. 

Thí dụ tính tổng hai số nguyên từ hàm sum
#!/bin/bash
function sum {
     if [ ! "$#" = "2" ]; then
         echo "ERROR: the number of parameters must be 2"
         return
     else 
         local total
         let "total = $1 + $2"
         echo "is $total"
    if
}
value=$(sum 2 3)
echo "total of 2 and 3 $value"

16.3  Gọi các hàm đã được định nghĩa trong một tập tin khác :

Như có nhắc trong phần đặc điểm,  để việc chia sẽ mã nguồn được tiện lợi, BASH hỗ trợ một lệnh để tải một tập tin khác có chưá các thông tin hay các hàm và dùng nó để chia sẽ.  Tập tin được tải có thể có mã nguồn trực tiếp sử dụng các biến hay tham số đã được định nghiã trong tập tin khai báo. Ngược lại, tập tin khai báo có thể gọi tất cả các hàm hỗ trợ sẵn có trong tập tin được tải.

Cú pháp dể khai báo tải  một tập tin

. <TÊN_TẬP_TIN_HÀM> hay là source <TÊN_TẬP_TIN_HÀM>

Thí dụ: Gọi hàm từ các tập tin ở nơi khác. 

Nội dung của tập tin myFunc chứa định nghiã của các hàm, nó cần được tải và gọi bởi một văn lệnh khác
#!/bin/bash
#file name myFunc
func1 ()
{
    if [ $#  -eq 1 ];then
         echo "the 1st parameter passed into func1 is $1"
    elif [ "$1" = "" ]; then
         echo "no parameter passed into func1"
    else
         echo "more than one parameters passed"
    if
}

internal_Usage_Func ()
{
    echo "error : $*" 2>&1
    echo "program $0 is terminated"
    exit 1
}

func2 ()
{
   #recursive and internal function calling demo
   if  [ ! "$#" = "1" ]; then
         internal_Usage_Func "func2() called from $0 require single argument"
         #in this case $0 will be the invoking script (mother)
         #so it not be Expect as myFunc
   else
       
 local number=$1
         # Variable "number" must be declared as local,
         # otherwise this doesn't work.
         if [ $number -eq 0 ];    then
             factorial=1    # Factorial of 0 = 1.
         else
             let "decrnum = number - 1"
             func2 $decrnum  # Recursive function call.
             let "factorial = $number * $?"
         fi
         return $factorial
   fi
}

Nội dung của tập tin chính bao gồm việc khai báo tải và gọi các hàm từ tệp myFunc
#!/bin/bash
#file name mother
. myFunc  #declaring function will be loaded
# equivalent declaring:  source myFunc
#now calling functions of file myFunc
echo "func1 with 1 argument"
func1 hi
echo "func1 with 2 arguments"
func1 hello world
echo "---------"
#testing func2 recursive function
N=3
func2 $N
echo "factorial of 3 is $?.  This number is retrieved from func2"
echo "now test the internal function call"
func2  #no argument to trigger

The output when invoking mother should look like:
#func1 with 1 argument
#the 1st parameter passed into func1 is hi
#func1 with 2 arguments
#more than one parameters passed
#--------
#factorial of 3 is 6
#error : func2() called from mother require single argument
#program mother is terminated"

 


A14 Sử dụng trình dịch GNU C/C++

A14.1 Mở đầu

GNU C/C++ là một trình biên dịch được dùng phổ biến nhất trong Linux để phát triển các phần mềm. Có hai cú pháp cơ bản cho việc biên dịch đơn giản là

  • gcc [Tham_số | Tên_tập_tin] :  Cho tất cả cá chương trình ngôn ngữ C
  • g++ [Tham_số | Tên_tập_tin] :  Cho tất cả cá chương trình ngôn ngữ C++

Những tên mở rộng của các tập tên mã nguồn mà trình dịch GNU dùng mặc định là:

  • .c: của tập tin mã nguồn trong ngôn ngữ C: tiền xử lý, biên dịch, tạo tệp assemble
  • .C, .cc, and cxx:  của tập tin mã nguồn trong ngôn ngữ C++: tiền xử lý, biên dịch, tạo tệp assemble
  • .m:  nguồn objective-C: tiền xử lý, biên dịch, tạo tệp assemble (hợp ngữ)
  • .i:  tiền xử lý C; biên dịch sang hợp ngữ
  • .ii: tiền xử lý C++; biên dịch sang hợp ngữ
  • .s: mã assemble; hợp ngữ
  • .S: mã assemble; tiền xử lí, hợp ngữ
  • .h: tập tin tiền xử lí nhưng thường không được (hay không cần) sử dụng (gọi) trong dòng lệnh để dịch

Để đọc toàn bộ chi tiết, hãy gõ lệnh man gcc hay man g++.

A14.2 N hững tham số thông dụng trong trình dịch GNU:

  • -x [ <ngôn_ngữ> ] :  khai báo đặc biệt <ngôn_ngữ>  các các tập tin theo sau cho đến khi có tham số -x kế tiếp. Các giá trị của tham số ngôn ngữ là: c, objective-c, c-header, c++, cpp-output, assembler, và  assembler-with-cpp .  Nếu dùng tham số -x mà không có các giá trị ngôn ngữ đi kèm thì trình dịch sẽ bỏ qua tham số này
  • -c : dịch và tạo hợp ngữ cho tập tin mã nguồn nhưng không tiến hành liên kết (link).  Do mặc định, tập tin đối tượng xuất ra sẽ có phần tên mở rộng là .o và có tên là tên của tập tin nguồn
  • -S : Ngừng sau khi biên dịch hợp lệ và tạo ra các tập tin hợp ngữ với tên mở rộng là .s thay cho .c hay .i '
  • -o <Tên_Tập_tin> : Xuất ra tập tin <Tên_Tập_tin>   thay vì dùng tên mặc định (thường là a.out )

Thí dụ

Contain of  first.C

#include "iostream.h"
int main ()
{
    cout << "hello\n";
    return 0;
}

to compile and receive the output as hello:
g++ first.C -o myhello

Alternately, we can compile it by separate the process into 2 stages:
g++ -c first.C     (generate object file)
g++ first.o -o myhello

To run the myhello command
#./myhello
the message should look like
#hello

A14.3 Các tham số quan trọng liên quan đến ngôn ngữ:

  • -ansi :   hỗ trợ toàn bộ chuẩn ANSI C;tắt các chức năng GNU mà có thể tạo xung đột với ANSI C như là các từ khoá asm, inline, typeoff key words; tuy nhiên, các từ khoá thay thế như là __asm__, __extension__, __inline__, __typeoff__ vẩn hữu hiệu
  • -fno-asm :   không công nhận các từ khoá asm, inline, typeoff . Thay vào đó, vẩn có thể dùng __asm__,  __inline__, __typeoff__ .
  • -fno-buildin : Không công nhận các hàm cho sẵn. Các hàm này  bao gồm cả  ext, abort, abs, allocat, cos, exit, fabs, labs, memcmp, memcpy,sin, sqrt, strcmp,strcpy, strlen
  • -funsigned-char Đồng hoá kiểu char như là unsigned char.
  • -fsigned-char Đồng hoá kiểu char như là signed char.
  • -funsigned-bitfields : cài các bit field như là không dấu (unsigned). Mặc định cho các bitfield là dấu.

A14.4 Các tham số tiền xử lí quan trọng:

  • -include <Tên_Tập_tin>: Xử lý tập tin <Tên_Tập_tin> như là tập tin nhập trước khi xử lí tập tin nhập thông thường. Tập tin <Tên_Tập_tin> sẽ được dịch đầu tiên.
  • -imacro <Tên_Tập_tin>: Xử lý tập tin <Tên_Tập_tin> như là tập tin nhập và loại bỏ thông báo tạo ra từ tập tin <Tên_Tập_tin> trước khi xử lí tập tin nhập thông thường.  Điều này sẽ làm cho tất cả các macro được định nghiã trong  tập tin <Tên_Tập_tin> có hiệu lực cho main .
  • -idirafter <Tên_Thư_Mục> : thêm  thư mục <Tên_Thư_Mục> vào đường dẫn bao gồm thứ hai. Các thư mục của đường dẫn bao gồm thứ hai  (second include path) sẽ được tìm kiếm mỗi khi có tập tin header không thể tìm thấy ở bất kì thư mục nào của các bao gồm chính (main include) . (Bao gồm chính có thể thêm vào bằng cách dùng tham số -I)

A14.5 Các tham số quan trọng dùng trong liên kết:

  • -l<Tên_Thư_Viện> : Dùng tên thư viện <Tên_Thư_Viện> khi tiến hành  bước liên kết (linking). Bộ máy liên kết (linker) sẽ tìm trong các thư mục chuẩn tập tin thư viện có tên lib<Tên_Thư_Viện>.a
  • -static :  không liên kết kiểu chia sẽ mà thay vào đó là dùng cách liên kết tĩnh.  (Trong liên kết tĩnh các thư viện sẽ được chép lại và nối vào trong tập tin khi dịch ra do đó cõ tập tin xuất sẽ lớn hơn bình thường.  Tuy nhiên, khi thực thi tập tin này sẽ không bị lệ thuộc vào sự tồn tại của các thư viện nữa --- vì nó đã có sẵn các du liệu thư viện này bên trong nội dung)

    Thí dụ : Khi tạo ra một lệnh mount đặc biệt lệnh này sẽ không đòi hỏi các thư viện chia sẽ có thể tiện dùng trong các dĩa CD ROM Linux tự khởi động được (bootable CD ROM):

    Content of file mountcd.c
    #include <sys/mount.h>
    int main (int argc, char ** argv)
    {
       int dat=0;
       return mount(argv[1], argv[2], argv[3], MS_RDONLY | MS_MGC_VAL, &dat);
    }

    to comile use this command"
    gcc -static mountcd.c -o mountcd

A14.6 Tham số về thư mục thông dụng:

  • -I <Tên_Thư_Mục> : thêm thư mục <Tên_Thư_Mục>  vào trong danh sách các thư mục mà trình dịch sẽ tìm kiếm các tập tin bao gồm

A14.7 Tham số cảnh cáo:

  • -Wall : sử dụng mọi loại thông báo cảnh cáo; dùng tham số này sẽ rất có lợi cho việc thực tập viết mã trong C/C++

A15 Tác trình và cách tạo ra

A15.1 Khái niệm và đặc tính:

Tác trình  (daemon) (1) là các tiến trình chạy trong  nền (background)  nhằm thực hiện một thao tác hệ thống liên hệ. Khác với các module hay bộ điều vận, tác trình  là chương trình riêng  không phải là bộ phận của hạt nhân. Đa số các tác trình bắt đầu ở thời gian khởi động máy và tiếp tục tải cùng với thời gian hoạt động của máy. Một số tác trình khác chỉ chạy khi cần và có thể ngưng khi không cần thiết nữa. Trong khi một số tác trình có khả năng tương tác với nhiều chương trình liên quan thì số lớn các tác trình chỉ tương tác được với các chương trình viết riêng cho nó. Chẳng hạn như tác trình xinetd điều có ảnh hưởng một lúc đến nhiều chương trình như là ftp, talk, telnet,figner,vnc ... thì kbd là một tác trình đặc thù cho bàn phím trong X window.

So sánbh với hệ thống Windows thì các tác trình có chức năng tương tự như các dịch vụ (service) hay các chương trình nằm ở thanh tác vụ (taskbar)  của windows.  

Một tác trình thường sau khi tải sẽ được giữ trong bộ nhớ và lắng nghe các yêu cầu từ các chương trình tương ứng để thực hiện các thao tác đòi hỏi hay trả lời cho các yêu cầu của chúng.  Một số không ít các tác trình chỉ phục vụ cho một chương trình đặc trưng và thường sẽ bị kết thúc khi chương trình đó không họat động nữa

A15.2 Tạo một tác trình trong C/C++ :

Hầu hết các tác trình đều dùng ngôn ngữ C hay C++ để tải chương trình vào bộ nhớ và chạy trong nền Sau đây là phần cốt lõi mã C mô tả:

Thí dụ:

//file name daemon.c
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#define MAX_ARG 10
int daemon_init(void);
 
int main(int argc, char * argv[])
{
  daemon_init();


 
<Khối_mã_thiết_lập_tác_trình>

  return 0;
}
 
int daemon_init(void)
{
  pid_t pid;
  if ((pid = fork())<0) return(-1); //to create an independ process
  else if (pid != 0) exit (0);
  setsid(); //get an SID for it to avoid becoming an orphan process
  chdir("/");
  umask(0);
  //close(STDIN_FILENO);
  //close(STDOUT_FILENO);
  //close(STDERR_FILENO);


  return(0);
}

Sau khi <Khối_mã_thiết_lập_tác_trình> bởi các dòng mã nguồn thích hợp, bạn có thể dịch thành daemon bằng lệnh sau:

gcc daemon.c -o myCdaemon

Lệnh trên sẽ tạo ra một tác trình có thể được gọi và tải trực tiếp.  Tuy nhiên, để thấy rõ hoạt động của tác trình này,  trong <Khối_mã_thiết_lập_tác_trình> có thể đặt vào đó  vòng lặp để lắng nghe (hay đợi) trả lời cho một yêu cầu, hoặc có thể như bài tập, người lặp trình hãy thay bằng  vòng lặp chỉ cần thi hành lệnh tạo mới tên 1 tập tin và đóng lại rồi thi hành lệnh sleep() trong vài giây.

Lưu ý:  

  • Tùy theo ý định sử dụng người lập trình có thể đóng các ngỏ xuất nhập chuẩn (nếu như không muốn cho tác trình đó liên lạc được với các ngỏ xuất nhập chuẩn này). Trong trường hợp chương trình cần nhiều tính bảo mật thì nên cứu xét tới việc đóng các thiết bị đó.  3 dòng màu cam được viết dạng bị chú trong đoạn mã trên mô tả các lệnh đóng chúng lại.

  • Một số hệ điều hành còn cung cấp những lệnhh đặt biệt để nâng một chương trình mệnh lệnh bất kì thành một tác trình như là lệnh startproc , start_daemon, checkproc tìm thấy trong các sản phẩm của  SUSE. Phần mã trên cũng cho thấy cách để tạo mệnh lệnh trở thành tác trình

  • Các hệ điều hành mới còn hỗ trợ một hàm đặc biệt là daemon() . Hàm này hỗ trợ cho việc tạo một tác trình; rất tiện dụng nếu người viết chỉ dùng mã C/C++ để thiết lập tác trình. Hàm này đòi hỏi câu lệnh tiền xử lý #include <unistd.h> .  Hãy dùng lệnh man daemon dể xem chi tiết cách sử dụng. việc thử nghiệm cách dùng này xem như bài tập

A15.3 Tác trình truyền thống :

Theo truyền thống thì các tác trình sẽ hỗ trợ ít nhất hai tham số tiêu chuẩn là  startstop .  Tuy nhiên không có gì bắt buộc nguời tạo tác trình phải theo truyền thống đó nếu không có ý định dùng tác trình này trong các quá trình khởi động máy. Nhiều tác trình còn báo lỗi và không hoạt động nếu người gọi không xử dụng đến các tham số cho phép.  Cú pháp chung để gọi một tác trình là:

<TÊN_TÁC_TRÌNH>  <Tham_Số>

Sau đây là các  <Tham_Số> thường thấy:

  • start :  dùng để khởi động tác trình

  • stop : dùng để ngưng tác trình

  • restart : ngưng tác trình đang chạy nếu thành công thì lập tức khởi động lại nó

  • status : thông báo tình trạng hiện tại của tác trình

Rất nhiều tác trình thực sự bao gồm hai phần chính: 

  1. Phần mã nhị phân (mã máy) cốt lõi chỉ chứa lệnh vận hành là phần lệnh được mô tả trong A15.2

  2. Phần bao gói bên ngoài (wrap).  Phần này thường được viết bằng văn lệnh nhằm cung ứng hệ thống tham số chuẩn như kể trên và thực thi.  Việc dùng văn lệnh để tạo phần bao gói sẽ được trinh bày sơ lược trong A15.4

Hầu hết các tác trình quan trọng của Linux được chứa trong thư mục /etc/init.d .  Ban đầu tên của tác trình thường kết thúc bằng kí tự d   (viết tắt từ chữ daemon) nhưng càng sau này truyền thống này ít còn được chấp hành.

A15.4 Văn lệnh làm bao gói cho một tác trình:

Thí dụ sau đây cho thấy cách để bao gói một tác trình tên là mydaemon . Tập tin bao gói này tên là myd .

#! /bin/sh
# Copyright (c) 1998-2001 ..... All rights reserved.
#
# Author: ....
#
# /etc/init.d/myd

# implement this 2 lines if mydaemon use a configuration internal functions in 'mydconfig'
#test -r /etc/sysconfig/mydconfig | exit 6
#. /etc/sysconfig/mydconfig

# 0 - success
# 1 - generic or unspecified error
# 2 - invalid or excess argument(s)
# 3 - unimplemented feature (e.g. "reload")
# 4 - insufficient privilege
# 5 - program is not installed
# 6 - program is not configured
# 7 - program is not running

DAEMON_NAME=<Full_name_of_Daemon>  //place the full name of mydaemon here
MYD_BIN="/usr/bin/init_daemon"     //for SUSE use: MYD_BIN=/sbin/start_daemon

test -x $MYD_BIN || exit 5
 
#Implement specific OS function support here (ex ". /etc/rc.status" as in SUSE)

case "$1" in
start)
   #the daemon mydaemon is invoked only in this line
   echo -n "Starting mydaemon"
   ($MYD_BIN $DAEMON_NAME <Parameter_list>)  || return=7
   #please replace <Its_Parameter_list> by the properly arguments
;;
stop)
   echo -n "Shutting down mydaemon "
   kill $(pgrep $DAEMON_NAME)
;;
restart)
   $0 stop && $0 start || return=1
;;
status)
   echo -n "Checking for service mydaemon: "
   # Status return:
   # 0 - service running
   # 1 - service dead, but /var/run/ pid file exists
   # 2 - service dead, but /var/lock/ lock file exists
   # 3 - service not running
   PS=`pgrep $MYD_BIN`
   if [ ! "$PS" = "" ]; then
      return=0
   else
      return=3
   fi
;;
*)
   echo "Usage: $0 {start|stop|status|restart}"
   exit 1
esac
exit $?

Trong thí dụ trên, các dòng chữ màu cam cho thấy vị trí duy nhất mà mydaemon được gọi (trong dạng tên đầy đủ).  Trong thực tế, tuỳ theo người lập trình kiến trúc cho tác trình của mình thì mẫu thí dụ trên có thể được điều chỉnh lại

Lưu ý:

  • Nếu dùng một daemon độc lập  (như mô tả  trong thí dụ 15.2 thì tất cả dòng màu cam  nên được xóa đi và dòng màu cam
    ($MYD_BIN $DAEMON_NAME <Parameter_list>)  || return=7   được thay bằng dòng
    (<DAEMON_NAME> <Parameter_list>) || return 7 . Trong đó, <DAEMON_NAME> <Parameter_list>
    là tên đầy đủ của tập tin tác trình  và tham số cần gọi
  • /usr/bin/init_daemon là một lệnh có khả năng tải một lệnh khác bất kì trở thành một tác trình. Bước 2 trong A15.6 sẽ chỉ dẫn các tạo ra lệnh init_daemon này.
  • Tùy theo hệ điều hành có thể có hỗ trợ một số mệnh lệnh để việc thiết trí một văn lệnh bao gói được phù hợp!  Tuy nhiên trong mọi trường hợp thì việc viết một văn lệnh đúng sẽ không bị từ chối khi được gọi.
  • Trong nhiều hệ điều hành thì biến MYD_BIN đã có sẵn tiện ích hỗ trợ như là lệnh start_daemon của SUSE người dùng không cần phải tạo ra lệnh init_daemon như trong mã thí dụ cho nghiã là chỉ cần viết thành  MYD_BIN=/sbin/start_daemon.

A15.5 tác trình khởi động

Như đã đề cập, một số lớn tác trình bắt đầu tiến trình của nó trong lúc máy khởi động.  Các tiến trình này được gọi tùy theo cấp độ khởi động và tùy theo thứ tự ưu tiên. Nguyên lý chung là các chương trình khởi động kể cả các tác trình (nếu cần) đều được tạo ra các liên kết mềm (softlink) trong các thư mục khởi động rc<n>.d , Trong đó,  <n> có thể là một trong các cấp độ khởi động (0,1,2,3,4,5, 6 ) (2)  hay có giá trị S (S là chữ viết tắt của "single user"). Các liên kết này được đặt tên theo một luật rõ ràng:

  • Các tác trình được gọi trong quá trình máy bắt đầu chạy đều có tên bắt đầu bằng kí tự S

  • Các tác trình được gọi trong quá trình bắt đầu tái khởi động hay ngưng (halt) máy đều có tên bắt đầu bằng chữ K . Thông thường, quá trình này dùng để ngưng các tác trình đã được chạy lúc khởi động máy

  • Hai kí tự kế tiếp xy (ở vị trí thứ nhì và ba) của tên chương trình khởi động tạo thành số nguyên bắt đầu từ 00 cho tới 99 . Con số này quy định thứ tự ưu tiên để trình khởi động nào được thi hành trước tiên. Số nhỏ hơn sẽ được gọi trước. (như vậy giữa  S13abcdS40abcd thì S13abcd sẽ có ưu tiên hơn và được thì hành trước S40abcd trong lúc khởi động)

  • Các tác trình khởi động này khi được gọi sẽ tự động được nhận tham số start nếu nó có tên bắt đầu bằng kí tự S và tham số stop nếu kí tự này là K (3)

ls -Al /etc/init.d/rc3.d
lrwxrwxrwx 1 root root 7 2005-09-09 06:17 K03cron -> ../cron
lrwxrwxrwx 1 root root 10 2005-09-09 06:17 K05postfix -> ../postfix
lrwxrwxrwx 1 root root 8 2005-09-09 07:34 K05smbfs -> ../smbfs
lrwxrwxrwx 1 root root 8 2005-09-30 04:21 K06dhcpd -> ../dhcpd
lrwxrwxrwx 1 root root 7 2005-09-09 06:17 K08slpd -> ../slpd
lrwxrwxrwx 1 root root 9 2005-09-09 03:12 K16syslog -> ../syslog
lrwxrwxrwx 1 root root 9 2005-09-09 03:12 K21random -> ../random
lrwxrwxrwx 1 root root 12 2005-09-12 07:03 K35mountdev -> ../mountdevd
..............
lrwxrwxrwx 1 root root 9 2005-09-09 03:12 S01random -> ../random
lrwxrwxrwx 1 root root 9 2005-09-09 03:12 S06syslog -> ../syslog
lrwxrwxrwx 1 root root 17 2005-09-09 06:21 S12running-kernel -> ../running-kernel
lrwxrwxrwx 1 root root 7 2005-09-09 06:17 S14slpd -> ../slpd
lrwxrwxrwx 1 root root 8 2005-09-30 04:21 S16dhcpd -> ../dhcpd
lrwxrwxrwx 1 root root 10 2005-09-09 06:17 S17postfix -> ../postfix
lrwxrwxrwx 1 root root 8 2005-09-09 07:34 S17smbfs -> ../smbfs
lrwxrwxrwx 1 root root 7 2005-09-09 06:17 S19cron -> ../cron
lrwxrwxrwx 1 root root 12 2005-09-12 07:02 S88moundev -> ../mountdevd

..................
Phần  trích hiển thị trả về của lệnh ls cho thấy các softlink của các daemon. Hãy lưu ý cách đặt tên của các soflink này và thứ tự ưu tiên của chúng (bằng các số theo sau S và K)

Như vậy, để có thể tạo ra một tác trình sau khi đã được bao gói thì:

  1. Chép tập tin đó vào thư mục /etc/init.d (chẳng hạn đó là mydaemond ).  Đổi thuộc tính tập tin này sang +x.

  2. Chuyển thư mục hiện hoạt sang một trong các thư mục khởi động (thường là rc3.d   ) (4)  (dùng lệnh cd )

  3. Tạo liên kết mềm S<xy><TÊN_TÁC_TRÌNH> liên kết về mydaemond bằng lệnh:   ls -s /etc/init.d/mydaemond S33mydaemon

  4. Tạo liên kết mềm K<mn><TÊN_TÁC_TRÌNH> liên kết về mydaemond bằng lệnh:   ls -s /etc/init.d/mydaemond K77mydaemon

  5. Tái khởi động máy hay gọi telinit để hoạt hoá các tác trình

A15.6 Tạo tác trình khởi động với văn lệnh BASH

Để tạo một tác trình bằng văn lệnh có thể xem xét thí dụ sau đây như là khuôn mẫu ban đầu

Bước1: Viết tác trình bằng BASH hay bất kì dạng văn lệnh nào.  chú ý tác trình chỉ có ý nghiã khi nó được tải và lưu lại trong bộ nhớ một cách bề vững, nên dó đó, trong phần lắp đặt có thể đặt vào đó một vòng lặp chạy trong tru kì lâu dài (hay vĩnh viễn cho tới khi bị tiêu hủy).

Thí dụ: thí dụ sau sẽ cập nhật thông tin 10 giây một lần vào tập tin /root/mydaemon.txt cho đến khi vượt quá 5000 giây sẽ tự hủy hay nếu bị gọi lệnh kill

     !#/bin/bash
    #file: mydaemon - 1st demonstration of daemon
    #
    MSG="/root/mydaemon.txt"
    cnt=0
    while [ $cnt -lt 500 ]; do
        echo "$0 $*" > $MSG  #write all parameter including name of the script into $MSG
        echo "value of counter: $cnt" >> $MSG  #append counter value
        let "cnt += 1"
       sleep 10   #delay 10 second after each refresh data file
    done
    exit

Sau khi viết xong dùng lệnh chmod +x mydaemon đ ể thực thi hoá nó và thử chạy nó xem chương trình có bị lỗi hay không. (có thể gọi dạng ./mydaemon & để chạy thử nó trong nền) chứa tác trình thử nghiệm này trong thư mục /root .

Bước 2:  Tạo một lệnh để đưa một chương trình trở thành tác trình dùng mã nguồn C: Thay <Khối_mã_thiết_lập_tác_trình> trong thí dụ 15.2 bằng khối mã cụ thể sau

Thí dụ:

i=0;
switch (argc)
{
case 2:
    i=execlp(argv[1],argv[1],NULL);
    return(i);
case 3:
    i=execlp(argv[1],argv[1],argv[2],NULL);
    return(i);
case 4:
    i=execlp(argv[1],argv[1],argv[2],argv[3],NULL);
    return(i);
case 5:
    i=execlp(argv[1],argv[1],argv[2],argv[3],argv[4],NULL);
    return(i);
//you may wish to extend this switch command to support more argument calls for your particular daemon
default:
    printf("too many paramter. System not support\n");
    return(-1);
}

Dùng lệnh :  gcc daemon.c -o init_daemon để chuyển dịch nó sang mã nhị phân.  Sau đó chép lệnh này vào thư mục /usr/bin để dùng cho mọi tác lệnh sau này.  Có thể thử nghiệm lại sau khi dịch thành công bằng cách gõ câu lệnh  ./init_daemon /root/mydaemon và sau đó dùng lệnh
pgrep mydaemon parameter1 parameter2 để kiểm lại rằng mydaemon đã được tải thành công (lưu ý khi gọi lệnh init_daemon thì nhớ dùng tên đầy đủ của tập tin tác trình để làm tham số gọi). Nếu như không muốn tạo ra tác trình khởi động thì coi như bạn đã làm xong một tác trình thông thường

Bước 3: Tạo một gói bao cho tác trình mà bạn đã có và chép gói này vào thư mục /etc/init.d :

Thí dụ: Dùng mã sẵn có trong A15.3, thay các dòng màu cam bằng tên đúng của nó cụ thể là :

DAEMON_NAME=<Full_name_of_Daemon>  đổi thành
DAEMON_NAME=/root/mydaemon
$MYD_BIN $DAEMON_NAME <Its_Parameter_list>)  || return=7 đổi thành
($MYD_BIN $DAEMON_NAME 1 2;) || return 7

Chép tập tin myd này vào thư mục /etc/init.d . Nhớ dùng lệnh chmod +x /etc/init.d/myd để tạo đặc tính thực thì cho nó. Giờ có thể thư tải nó bằng cách  gọi lệnh:
/etc/init.d/myd start
Dùng lệnh
pgrep mydaemon
Để kiểm tra lại tác trình của bạn đã được tải và sau đó dùng lệnh
/etc/init.d stop
Và cũng dùng pgrep mydaemon để biết chắc tác trình mydaemon đã bi hủy

Bước 4: Tạo các liên kết mềm cho tác trình được tự động tải và dở tải khi máy chạy và tắt: Lựa chọn cấp khởi động n và thứ tự ưu tiên SxyKmn

Thí dụ:  Cấp khởi động 3mn=xy=33 ; thi hành lệnh sau đây để tao liên kết mềm (dùng lệnh find để tìm ra vị trí của thư mục rc3.d )

find /etc -name rc3.d | xargs -i ln -s /etc/init.d/myd {}/S33myd
find /etc -name rc3.d | xargs -i ln -s /etc/init.d/myd {}/K33myd

Như vậy là hoàn tất một tác trình có khả năng tự khởi động

A16 Sử dụng lệnh sed

A16.1 Khái niệm:

sed là lệnh có thể xem như là một chương trình thông dịch (intepreter) đơn giản dùng để soạn thảo dòng văn bản (streamline editor) không có tính tương tác (noninteractive). Vì sed có thể dùng trực tiếp và an toàn trên dòng lệnh một cách dể dàng nên nó thường được dùng trong các văn lệnh chung với các lệnh khác thông qua kĩ thuật ống dẫn truyền. sed sẽ hiển thị nội dung văn bản thay đổi theo dòng lên ngỏ ra chuẩn mà không làm thay đổi nội dung sẵn có của các tập tin.

Lưu ý: Linux OS sử dụng phiên bản GNU của sed nên nó có nhiều hỗ  trợ đặt thù cho phiên bản này và sẽ được xem như tiêu chuẩn trình bày trong phần phụ lục này

Các cú pháp thông dụng của sed là:

  • sed [Tham_Số] '<Chỉ_Thị>' <CÁC_TẬP_TIN_XỬ_LÝ>
  • sed [Tham_Số] -f <Tên_Tập_Chỉ_Thị_sed> <CÁC_TẬP_TIN_XỬ_LÝ>
  • sed [Tham_Số] -e '<Chỉ_Thị1>' -e '<Chỉ_Thị2>' -e '<Chỉ_Thị3>'... <CÁC_TẬP_TIN_XỬ_LÝ>

Lưu ý:

  • '<Chỉ_Thị>', '<Chỉ_Thị1>', '<Chỉ_Thị2>', '<Chỉ_Thị3>' ... là các chỉ thị soạn thảo mà sed hỗ trợ. Các chỉ thị này được đóng trong các dấu ngoặc dùng cho string ' (hay đôi khi dùng dấu  " )  khi dùng trực tiếp qua dòng lệnh.

  • Khi dùng tham số -f <Tên_Tập_Chỉ_Thị_sed> thì các lệnh áp dụng của sed sẽ được viết vào trong một tập tin (mỗi hàng một mệnh lệnh) và các lệnh này sẽ được thi hành theo thứ tự từng lệnh một và áp dụng lên các dòng của <CÁC_TẬP_TIN_XỬ_LÝ>.

  • Cũng như tham số -f, người ta có thể dùng dòng lệnh với nhiều tham số -e , theo sau mỗi tham số -e là một mệnh lệnh của tập tin <Tên_Tập_Chỉ_Thị_sed> theo thứ tự. Hiệu quả hoàn toàn tương đương nhau.

Thí dụ:

Tập tin mydat có nội dung như sau sẽ được sử dụng trong suốt phụ lục này

Joe         WA     Apple, mango          9
Mayer       TX     Orange,banana         7
Harry       AL     Peper, mango          4
Clara       UK     Peach, lemon          8
Holy        TX     Kiwi, pear            6
Smith       CA     Cherry, Smith's plum  10
Joesmith    CA     Apricot, lemon CA    3
Thomas      AZ     Banana, chili         6
CA          MA     Bean, apple           0

sed '3,6d' mydat 
là lệnh sẽ hiển thị mọi dòng của tập tin mydat ngoại trừ các dòng từ dòng thứ 3 đến dòng thứ 6.  Tức là các dòng: (lệnh d viết tắt cho chữ delete nghiã là xoá bớt)

Joe         WA     mango                 9
Mayer       TX     orange,banana         6.5
Joesmith    CA     Appricot, lemon       3
Thomas      AZ     banana, chili         6

sed 's![Ss]mith!John! mydat
là lệnh thay thế dòng đầu tiên có chữ Smith hay chữ smith thành chữ John và hiển thị nội dung tập tin mydat ra. Như vậy khi hiển thị tập tin mydat , chỉ có dòng thứ 6 và 7 tại vị trí lần đầu tiên xuất hiện chữ chữ Smith sẽ bị đổi thành John (lệnh s viết tắt cho chữ substitute nghiã là thay thế)
John        CA     cherry, Smith's plum  10
JoeJohn     CA     Appricot, lemon       3
Các dòng khác hiển thị không đổi

sed -e 's/Joe/John/g' -e 's/CA/FL/g'
là lệnh đổi tất cả các chữ Joe trong mỗi hàng thành John và tiếp tục thay tất cả các hàng ở mọi vị trí có chữ CA thành chữ FL . (trong lệnh s của sed , tham số g viết tắt cho chữ global nghiã là toàn bộ.)

A16.2 Các tham số quan trọng:

Ngoài hai tham số -e -f các tham số sau đây của lệnh sed có thể hữu dụng

  • -n: không hiển thị ra stdout như mặc định.  Như vậy để hiển thị các dòng xử lí thì người dùng có thể dùng lệnh p hay cờ hiệu p để hiển thị những gì cần thiết.
  • -r : Dùng biểu thức chính quy mở rộng trong các lệnh tìm kiếm thay vì dùng biểu thức chính quy thông thường

Thí dụ:

Với tập tin mydat trong thí dụ bên trên

sed -n '2,4p' mydat   sẽ chỉ hiển thị các dòng nội dung của tập tin từ dòng thứ 2 đến dòng thứ 4.

A16.3 Các chỉ thị (lệnh) được sed hỗ trợ

Cấu trúc của một mệnh lệnh trong sed dạng :

[Vùng_Địa_chỉ][!]<Lệnh>[Tham_số]

Trong đó, [Vùng_Địa_chỉ], [!], [Tham_số] là các thành phần có thể vắng mặt còn thành phần <Lệnh> luôn luôn có mặt trong mọi câu lệnh sed.

A16.4  [Vùng_Địa_chỉ] [!]

  •  [Vùng_Địa_chỉ]: Nếu không xuất hiện trong dòng lệnnh thì lệnh sed sẽ được áp dụng lên tất cả các dòng văn bản
  • Thành phần của [Vùng_Địa_chỉ]: Có thể ở trong các dạng cấu trúc
    1. <Dạng_thức> :  Thoả mãn các quy ước trong Biểu thức chính quy và có thể hỗ trợ biểu thức chính quy mở rộng bằng cách thêm vào một số ý nghiã của siêu kí tự mới khi dùng tham số -r dể gọi sed. Thành phần kiểu này sẽ được đóng trong khuôn khổ của một cặp  kí tự giới hạn. Một dùng để mở ngoặc chứa nội dung của <Dạng_thức>   và một để đóng ngoặc lại.  Kí tự giới hạn mặc định là  / . Một khi người dùng muốn thay đổi giá trị mặc định này thì phải định nghiã lại. Việc định nghiã đơn giản chỉ việc dùng dấu \<Kí_tự_giới_hạn> cho việc mở ngoặc và không thêm bớt gì khi đóng ngoặc (tức là sẽ dùng cùng kí tự <Kí_tự_giới_hạn> nhưng không có dấu \ trước nó.
    2. <n> :  dòng văn bản thứ n được chỉ định
    3. $ :  dòng cuối cùng nhập từ ngỏ vào
    4. +<n> :  xử lý cộng thêm <n> dòng văn bản chỉ có thể là thành phần thứ hai trong [Vùng_Địa_chỉ] (5)
    5. ~<n> :  xử lý tiếp cho đến khi thành phần thứ nhất trong [Vùng_Địa_chỉ] lặp lại <n> lần (5)
  • Một [Vùng_Địa_chỉ]  chứa một hoặc chứa tối đa hai thành phần mô tả trên mà được ngăn cách nhau bằng dấu phẩy ( , ):.
    1. Nếu [Vùng_Địa_chỉ] có duy nhất một thành phần  thì sed chỉ thực thi <Lệnh>  lên những dòng văn bản nào thoả mãn nội dung yêu cầu của thành phần
    2. Nếu [Vùng_Địa_chỉ] có hai thành phần (ngăn cách nhau bằng dấu phẩy)  thì sed  thực thi <Lệnh>  lên những dòng văn bản bắt dầu từ dòng dầu tiên thoả mãn yêu cầu của  thành phần thứ nhất và chấm dứt thực thi ở dòng văn bản nào thỏa mãn nội dung của thành phần thứ nhì (hoặc đến hết tập tin nếu không có dòng nào thoả mãn thành phần này)
  • Nếu  [Vùng_Địa_chỉ] theo sau bởi dấu chấm than !   thì việc áp dụng lệnh sed sẽ đảo ngược hoàn toàn miền làm việc tức là nó chỉ áp dụng lên tất cả các dòng nằm ngoài  [Vùng_Địa_chỉ]
  • Theo mặc định thì từng dòng văn bản của ngỏ vào sẽ được xem xét nếu dòng đó tương hợp với [Vùng_Địa_chỉ] thì dòng đó sẽ được xử lí tiếp tục. Trong mục này, ta gọi dòng xử lý là các dòng văn bản thoả mãn được các điều kiện đòi hỏi của [Vùng_Địa_chỉ]

Thí dụ:

  • 2,4 vùng địa chỉ này chỉ cho phép xử lý lệnh sed trên các dòng từ 2 dến  4 của văn bản. Như vậy, lệnh  
    sed -n '2,4p' mydat
    sẽ chỉ in ra từ nội dung của mydat các dòng 2,3 và 4.
  • /ana/,5 vùng địa chỉ này chỉ xử lí lệnh sed từ dòng văn bản nào bắt xuất hiện chữ May và ngưng xử kí kể từ sau dòng 5.  Như vậy, lệnh
    sed  '/ana/,5d' mydat
    sẽ hiển thị tất cả các dòng ngoại trừ các dòng kể từ dòng thứ 2 (có nội dung phần tô màu cam   Mayer       TX     orange,banana         6.5  thoả mãn dạng thức /ana/) cho đến dòng thứ 5 (tức là các dòng 3,4, và 5 tiếp theo sau)
  • 4   chỉ xử lý dòng thứ 4. Như vậy, lệnh
    sed '4i\-----Come from United Kingdom-------' mydat
    sẽ hiển thị toàn bộ mydat và có chèn thêm dòng -----Come from United Kingdom------- vào dòng thứ 4. (lệnh i viết tắt từ chữ insert)
  • /Smith/! Sẽ xử lí tất cả các dòng ngoại trừ những dòng nào chứa chữ Smith. Như vậy, lệnh:
    sed -n '\;Smith;!'p mydat
    sẽ hiển thị toàn bộ nội dung mydat loại trừ dòng  Smith       CA     cherry, Smith's plum  10. Lưu ý: trong thí dụ này chúng ta đã định nghiã dấu ; như là một kí tự giới hạn

A16.5 Biểu thức chính quy trong sed:

A16.5.1 Hỗ trợ thông thường

A16.5.1.1 Dùng siêu kí tự & : Đa số các lệnh  đều liên quan đến việc tìm một dạng thức của dòng chữ nên sed hỗ trợ các siêu kí tự trong  biểu thức chính quy thông thường và ngoài ra nó còn quy ước thêm một siêu kí tự có vị trí đặc biệt đó là dấu & .

Siêu kí tự & dùng để thay thế cho chuỗi kí tự của dòng văn bản nào tương hợp với dạng thức của biểu thức chính quy trong dòng văn bản đang đưọc xử lí.  Điều này ra%'t tiện lợi khi soạn thảo mà các dòng văn bản có nhiều đọan thoả mãn dạng thức của biểu thức chính quy.

Thí dụ lệnh sau đây sẽ thay tất cả các từ apple bởi từ apple CA và các từ Apple bởi từ Apple CA . (xem lại dòng đầu tiên và dòng cuối cùng của mydat )
sed 's/[Aa]pple/& CA/g' mydat

A16.5.1.2  Dùng cặp siêu kí tự \(<Dạng_thức>\): Trong truờng hợp muốn thay thế chỉ một bộ phận của biểu thức chính quy thì người lập trình có thể dùng đến cặp siêu kí tự \( \). Cặp siêu kí tự này có thể xuất hiện nhiều lần trong một biểu chức chính quy. Mỗi cặp như vậy sẽ đánh dấu một dạng thức con (được đóng trong cặp mở \( và đóng \) ngoặc) của biểu thức. Khi có dòng văn bản tương hợp được xử lí, thì:

  • Nội dung chuỗi kí tự con của dòng văn bản tương hợp với \(<Dạng_thức>\) đầu tiên sẽ được lưu giữ trong một bộ đệm kí hiệu là \1
  • Nội dung chuỗi kí tự con của dòng văn bản tương hợp với \(<Dạng_thức>\) thứ nhì sẽ được lưu giữ trong một bộ đệm kí hiệu là \2
  • ...
  • Có tối đa 9 bộ đệm để lưu giữ như trên (từ \1, \2, ...\9 )
Thí dụ:

#content of mytext
This apple is a kind of American fruit
This mango is a kind of Asian fruit
This kiwi is a kind of African fruit

sed 's/This \(.*\) is .* of \(.*\) fruit/\2 \1 is a kind of fruit/' mytext

Lệnh trên sẽ trả về kết quả là
American apple is a kind of fruit
Asian mango is a kind of fruit
African kiwi is a kind of fruit
Trong các dòng xử lí thì các chữ có màu cam được lưu giữ như là \1 còn chữ màu tím lưu giữ như là \2

Ngoài ra, sed còn hỗ trợ chế độ dùng Biểu thức chính quy mở rộng trong đó sử dụng thêm các siêu kí tự quy  ước mới thông qua tham số -r

A16.5.2 Bảng hỗ trợ biểu thức chính quy mở rộng của sed -r:

Ngoài các siêu kí tự trong biểu thức chính quy, khi dùng tham số -r, sed sẽ hỗ trợ thêm các siêu kí tự, quan trọng là:
Siêu kí tự Ý nghiã Thí dụ (RE) Tương hợp với  Không
tương hợp với
\b Biên giới của một từ  \bfile\b  ' file', ' file '  myfile, file1
\B Không là biên giới
của một từ
 \Bfile  'myfile',  'file' ' file' '.file'
\w Kí tự là một chữ cái
hay một chữ số
 f\w*\.dat  file.dat, f1.dat, ...   f_.dat, f-i.dat
\W Kí tự không phải là chữ cái
hay chữ số
 file\W tương đương với RE:
 file[^a-zA-Z0-9]
 f1, file
\r Kí tự xuống hàng
(carriage return)
     
\d<xy> Kí tự có mã ASCII là <xy>
trong dạng thập phân
 dat\d97 tương đương với: data
(mã ASCII của kí tự a là 97)
 
\o<xy> Kí tự có mã ASCII là <xy>
trong dạng bát phân
     
\x<xy> Kí tự có mã ASCII là <xy>
trong dạng thập lục phân
     

A16.6 Các nhóm lệnh thông dụng của  sed

A16.6.1  Nhóm lệnh soạn thảo
Lệnh Chức năng Thí dụ (RE) Giải thích
a\ <Dòng_thêm_vào> Chép nối dòng
<Dòng_thêm_vào>
vào dòng đang xử lí
sed '/CA/a\Californian!' mydat Hiển thị các dòng
trong mydat
nếu dòng có chữ CA
thì chép nối
vào đó dòng chữ
 Californian!
c\ <Dòng_thêm_vào> Thay thế dòng hiện tại bằng
<Dòng_thêm_vào>
sed '/kiwi/c"erase kiwi line"' mydat Hiển thị các dòng
trong mydat
nếu dòng nào
có chữ kiwi
thì thay bằng
"erase kiwi line"
i\ <Dòng_thêm_vào> Chèn <Dòng_thêm_vào>
vào trước hiện tại
cat mydat| sed '/CA/iHello' Hiển thị các dòng
trong mydat
nếu là dòng
có chữ CA thì
chèn vào trước đó
dòng chữ Hello
d Xóa (không hiển thị)
dòng hiện tại
ls | sed '/\.txt$/d' Hiển thị danh mục
tập tin trong
thư mục hiện hoạt
nhưng bỏ qua các
tập tin kết thúc
bằng .txt
s Thay các dòng
có dạng thức bằng
dòng khác
-- Xem chi tiết dưới đây
   
y Chuyển dổi từng kí tự
theo ánh xạ xem
chi tiết dưới đây
   

A16.6.1.1 Ghi chú về lệnh s

Đây là lệnh rất thông dụng có cú pháp:

s/<Dạng_thức>/<Dòng_thay_thế>/<Cờ_hiệu>

Lệnh này cho phép tìm ra các đoạn chuỗi kí tự trong dòng văn bản hiện tại thoả mãn <Dạng_thức>  và thay thế bằng <Dòng_thay_thế> trước khi hiển thị ta màn hình. Ở đây, khác với các lệnh tìm dòng trong [Vùng_Địa_chỉ] hay lệnh grep nhằm tìm ra dòng văn bản thoả mãn điều kiện tưong thích, lệnh s chỉ tập trung trên đoạn văn bản của dòng nào thoả màn điều kiện tìm kiếm và chỉ thay thế đoạn văn bản đó bằng <Dòng_thay_thế>

Không như các thành phần của [Vùng_Địa_chỉ], kí tự giới hạn / mặc định của lệnh này có thể tái định nghiã bằng cách đơn giản là chỉ thay nó bằng kí tự mới mà không cần khai báo gì thêm.  Thí dụ:   cat myfile | sed '/1,10/s/Dec/December/g'   là lệnh hiển thị tập tin myfile nhưng trong 10 dòng đầu tiên nếu xuất hiện chữ Dec thì chữ đó sẽ bị thay bằng chữ December

Các tham số <Cờ_hiệu> có thể được dùng kết hợp với nhau, chúng bao gồm:

  • <n> Chỉ thay thế thực thể thứ n của chuỗi tương hợp với dạng thức trong dòng văn bản hiện tại.  Mặc định là 1 tức là vị trí đầu tiên mà dạng thức này tương hợp
  • g   Thay thế tất cả các thực thể tương hợp với dạng thức tìm thấy được trong dòng văn bản  (chữ g viết tắt cho chữ global)
  • i   Tìm thực thể tương hợp và không tính đến việc kí tự có hoa hay không
  • p   Hiển thị dòng này nếu có sự thay thế xãy ra; tiện dùng khi gọi bằng lệnh sed -n
  • w <Tên_Tập_Tin>  Viết lại vào tập tin tên <Tên_Tập_Tin> các dòng xử lý đã được thay thế

Thí dụ:

sed '/[gm]o/s/\bCA/FL/' mydat
sẽ tìm các hàng trong mydat nào chứa chữ go hay chữ mo (tức là các hàng 1,3,4,5) và nếu trong các hàng đó có chữ nào bắt đầu là CA thì thay CA thành FL

cat mydat | sed 's/lemon/apple/ig' 
sẽ chuyển nội dung của mydat vào lệnh sed và từ đây, dòng nào có các chữ lemon thì tất cả các chữ lemon này (cho dù là viết hoa hay không) đều bị thay thành chữ apple

sed 's~CA~NY~2' mydat 
Tất các dòng nào trong mydat có chứa sự xuất hiện của chuỗi kí tự CA lần thứ hai sẽ được xử lí bằng cách thay chuỗi xuất hiện CA lần thứ hai này thành chuỗi NY.  (Như vậy, chỉ có dòng
Joesmith    CA     Appricot, lemon CA 
được chuyển thành
Joesmith    CA     Appricot, lemon NY
Còn các dòng khác giữ nguyên 

sed '/[Ss]mith/s/$/**In Fast Eating Contest**/' mydat
Tất cả các dòng chứa chữ Smith hay smith trong mydat thi hành lệnh s: thay dấu đầu dòng (newline) bởi dòng chữ **In Fast Eating Contest**

A16.6.1.2 Ghi chú về lệnh y

Lệnh y là lệnh "chuyển dịch"  các kí tự theo ánh xạ 1-1 từ bảng kí tự  nguồn sang bảng kí tự ảnh có cú pháp dạng

y/<Bảng_kí_tự_nguồn>/<Bảng_kí_tự_ảnh>

Tương tự như lệnh s, kí tự giới hạn / có thể hoàn toàn thay thế bằng kí tự khác. Tuy nhiên, lệnh này không hỗ trợ các cờ hiệu

Thí dụ:

Lệnh sau đây sẽ chuyển các chữ số từ 0 đến 9 (chỉ tìm thấytrong cột cuối cùng) của tập tin mydat   thành các chữ từ A tới J một cách tương ứng (nghiã là 0 → A, 1 → B, 2 → C,..., 9 → J)  lên tất cả các dòng nào có chữ CA
sed '/CA/y~0123456789~ABCDEFGHIJ~' mydat

A16.6.2 Nhóm lệnh  thông tin dòng xử lý
Lệnh Chức năng Thí dụ (RE) Giải thích
 = Hiển thị số thứ tự của dòng xử lí  sed '/Smith/=' mydat Hiển thị trước
khi nội dung dòng
 p Hiển thị nội dung dòng  sed -n '/Smith/gp' mydat Thường dùng
kết hợp với sed -n

A16.6.3 Nhóm lệnh xử lý I/O
Lệnh Chức năng Thí dụ (RE) Giải thích
 e[lệnh] Thực thi một lệnh
hệ thống.
Nếu lệnh không
có mặt thì sed
lấy nội dung xử lí
làm lệnh để thi hành
 sed '/\blist\b/els' myfile Hiển thị nội dung
myfile
và nếu tìm thấy
từ list trong dòng xử lí
thì sẽ thực thi
lệnh ls rồi tiếp tục
 n Chỉ hiển thị dòng hiện tại
và nhảy tới xử lí
dòng kế tiếp,
dòng điều khiển cũng
chuyển tới lệnh sed kế tiếp
 (xem thí dụ phần kế) Dùng trong cách
viết lệnh sed lồng nhau
r [Tập_tin] Đọc nội dung của [Tập_tin]
và hiển thị nối tiếp vào trong
ngỏ ra, sau dòng xử lí
 sed '/^List:/r mylist' myform Nếu myform
dòng chữ List:
thì ngay sau dòng này
sed
sẽ hiển thị nội dung
tập tin mylist
w [Tập_tin] Chép nối nội dung của dòng
thoả mãn vào
[Tập_tin]
 sed '/CA/w ca.dat' mydat Chép nối vào tập tin ca.dat
các dòng tìm thấy trong
mydat
có từ CA
q [Exit_code] Chấm dứt lệnh ngay khi
[
Vùng_Địa_chỉ]

được tìm thấy
 sed '/lemon/q 1' mydat Hiển thị cho đến khi dòng
xử lí có chữ lemon xuất hiện
trong mydat thì ngưng
sau đó và trả về giá trị 1
Q [Exit_code] Tương tự lệnh q nhưng
không hiển thị dòng thoả mãn

[Vùng_Địa_chỉ]
 sed '/lemon/Q 1' mydat  

A16.6.4 Nhóm lệnh lưu giữ và trả về

Phần lệnh này đặc biệt thường dùng trong việc sử dụng lệnh sed lồng nhau (xem phần kế sau) hay trong các lệnh sed n'i tiếp nhau thông qua tham số -e .  Bằng cách cung ứng một bộ đệm tạm được đặt tên là vùng dạng thức (pattern space)
Lệnh Chức năng
 h Chép phần văn bản thoả mãn
[
Vùng_Địa_chỉ] vào bộ đệm tạm
 H Chép nối dấu đầu dòng và tiếp theo
là phần văn bản thoả mãn [Vùng_Địa_chỉ] vào bộ dệm tạm
 g Chuyển nội dung của vùng dạng thức trở vào dòng xử lý,
xóa nội dung của <Dạng _thức>.
 G Giống như g nhưng nội dung vùng nhớ đệm đưọc chép nối
thành dòng mới thay vì xoá nội dung của <Dạng _thức>
 x Đổi nội dung cho nhau giữa bộ dệm và nội dung của
<
Dạng _thức>

Thí dụ:

sed -e '/Ap/H' -e '$g' mydat

Thí dụ trên sẽ hiển thị toàn bộ mydat. Trong khi đó các dòng có chứa chữ Ap sẽ được lưu lại (nối nhau) trong bộ đệm và sau đó lệnh $g sẽ hiển thị lại nội dung của bộ đệm này ở dòng cuối cùng.

A16.7 Sử dụng các lệnh sed lồng nhau:

Trong nhiều trường hợp, người lập trình muốn xử lí một số dòng văn bản liên quan nhau thành khối (như trường hợp đọc các xml file chẳng hạn) thì sed hỗ trợ dạng phân nhánh như cú pháp sau:

sed '[Vùng_Địa_chỉ]{ <KHỐI_LỆNH;> } <TÊN_TẬP_TIN>

Lưu ý: Trong <KHỐI_LỆNH;>   thì mỗi lệnh của sed phải kết thúc bằng dấu chấm-phẩy ;

Thí dụ1:  Hoàn toàn tương tự như thí dụ trong A16.6, nhưng ở đây các dòng có chứa chữ Ap sẽ không được hiển thị và được giữ trong bộ đệm rồi sau đó mới hiển thị ra. như vậy tương đương với việc lấy các dòng đó ra và chuyển chúng xuống hiển thị cuối cùng

sed -e '/Ap/{H,d}' -e '$g' mydat

Thí dụ2: Thí dụ sau đây sẽ chuyển định dạng cho tập tin :

#content of mytext
This apple is a kind of American fruit
This mango is a kind of Asian fruit
This kiwi is a kind of African fruit

sed '/ of /{ h; s/.* of \(.* fruit\)/\1:/; p; x }' mytext

#the output should be
American fruit:
This apple is a kind of American fruit
Asian fruit:
This mango is a kind of Asian fruit
African fruit:
This kiwi is a kind of African fruit

Trong thí dụ trên, lệnh h lưu giữ lại dòng xử lí, trong khi lệnh s hiển thị các chữ dạng American fruit:, sian fruit:,African fruit: và sau cùng lệnh x cho xuất (hoán đổi) nội dung của bộ đệm ra


(1) Nghiã nguyên thuỷ của chữ Daemon là: ''là một linh hồn dợi sẵn mà có thể ảnh hưởng tới đặc điểm và cá tính của một người nào đó.  Từ "daemon được dùng như thuật ngữ computer đầu tiên bởi một thành viên người Anh lập trình trên máy CTSS ở MIT tên là MickBailey trong thập niên 1960.

(2) Các cấp độ khởi động cuả Linux bao gồm
  • 0 dừng máy
  • 1 một người dùng
  • 2-4 người dùng định nghiã
  • 5 dùng chế độ đồ họa X11
  • 6 Tái khởi động
  • Chế độ mặc định xác định trong  /etc/inittab
    • id:3:initdefault:
  • Để thay đổi cấp khởi dộng mặc định dùng  /sbin/telinit

(3) Thực chất khi khởi động máy một mệnh lệnh tương tự với đoạn mã sau đây đã được thi hành: (trường hợp này máy đang khởi động ở cấp 2)

for f in /etc/rc2./d/S*
{
   if [ -s ${f} ]; then
      /sbin/sh ${f} start
   fi 
}

(4)  Các thư mục khởi động này  thường nằm trong /etc hay trong /etc/init.d

(5) Các hỗ tợ này chỉ có trong phien bản của GNU (dùng trong Linux)

Bài kì tới: Lệnh BASH, Truy sửa lỗi , đa luồng, lspci, awk, makefile, rpm

© http://vietsciences.free.fr , http://vietsciences.org  và http://vietsciences2.free.fr  Làng Đậu