Professional Documents
Culture Documents
Linux - Scripting (Part 2)
Linux - Scripting (Part 2)
Linux - Scripting (Part 2)
SCRIPTING (PART 2)
Author: Nhã Phạm
OVERVIEW
Trong phần 1 của scripting, mọi người đã được làm quen cơ bản về viết một file script, các quy tắc cơ bản trong
scripting.
Phần 2 này mình sẽ giúp bạn một số cách dùng thường nhất với các xử lý thông tin trong scritp, tuy nhiên đây cũng
chỉ là những phần cơ bản, script sẽ tùy thuộc vào từng nhu cầu cụ thể mà sẽ có cách xử lý khác nhau.
Tham số
Đối với mình thì thường dùng tham số đi kèm chung với scritp vì nhiều lúc 1 script của mình sẽ xử lý nhiều liều lần
với các tác vụ khác nhau.
Cơ bản thì các tham số được gọi sau script như phần 1 đã đề cập.
# myscript.sh <tham số 1> <tham số 2> <tham số n>
Các tham số chạy kèm với script sẽ được định nghĩa như sau.
Ta có VD như sau.
# myscript.sh 1 2 3
Thì trong script các biến sẽ được định nghĩa như sau.
RESULT=$1+$2+$3
echo $RESULT
Và sau khi chạy script thì kết quả trả về trên màn hình sẽ là 6
Tuy nhiên, trên thực tế là bạn sẽ bỏ vào chuỗi để xử lý chứ không phải con số, ví dụ ta có bài toán như sau.
+ Tham số đầu tiên sẽ là encrypt hoặc decrypt, ta sẽ dùng condition statement để xác định mình cần encrypt
hay decrypt.
+ Tham số thứ 2 là tên file và vị trí file.
1
Ta sẽ điền tham số theo script như sau.
# myscript.sh <dec|enc> <file cần encrypt hoặc decrypt>
Ở đây, dec à decrypt và enc là encrypt. Trong script sẽ như thế này:
#!/bin/bash
if [ “$1” == “enc” ]; then
openssl enc -aes256 -pbkdf2 -k '12345678' -in $2 -out $2.enc
rm -f $2 # xóa file sau khi mã hóa
elif [ “$1” == “dec” ]; then
openssl enc -aes256 -pbkdf2 -k '12345678' -in $2.enc -out $2
rm -f $2.enc # xóa file encrypt sau khi đã decrypt
else
echo “file not found”
fi
Hoặc ta cũng có thể viết bằng cách sử dụng “CASE” statement như sau.
#!/bin/bash
case “$1” in
“enc”)
openssl enc -aes256 -pbkdf2 -k '12345678' -in $2 -out $2.enc
rm -f $2 # xóa file sau khi mã hóa
;;
“dec”)
openssl enc -aes256 -pbkdf2 -k '12345678' -in $2.enc -out $2
rm -f $2.enc # xóa file encrypt sau khi đã decrypt
;;
*)
echo “file not found”
;;
esac
Trên đây là cách sử dụng tham số kè theo đơn giản nhất, trên thực tế thì sẽ có nhiều cách hơn để áp tham số vào
bên trong script. Bạn có thể bỏ thêm thời gian đển nghiên cứu.
Condition statement.
Như đã nói ở phần 1, đối với Sysadmin, sử dụng If sẽ là rất nhiều vì chúng ta cần phải kiểm tra mọi dữ liệu có thể
có để tránh trường hợp bị lỗi, vì khi bị lỗi script sẽ tự thoát ra khỏi môi truòng đang chạy. Dưới đây là các kiểm tra
thường hay xài nhất đối với sysadmin.
Lưu ý: phần kiểm tra thường chỉ có true hoặc false tức là có hay không có nên mình sẽ sử dụng IF…ELSE làm
statement chính, nếu như kết quả cần kiểm tra có nhiều hơn có hay không có thì mình sẽ khuyến cáo sử dụng CASE
Ngoài ra khi bạn muốn đọc dữ liệu từ file text nào đó, bạn cũng phải đảm bảo là file đó có tồn tại hay không thì mới
bắt đầu đọc.
Việc kiểm tra thì chỉ cần dùng IF…ELSE để kiểm tra mà thôi.
if [ -f <vị trí file> ]; then
<câu lệnh thực thi nếu file có tồn tại>
else
<câu lệnh thực thi nếu file không tồn tại>
fi
2
Chú ý, đối với việc kiểm tra file đó không tồn tại thì ta chi cần thêm dấu “!” vào phía trước ký tự kiểm tra, nó sẽ như
thế này:
if [ ! -f <vị trí file> ]; then
<câu lệnh nếu file không tồn tại>
fi
VD, kiểm tra có tồn tại file myscript.log hay không, nếu không thì tạo mới.
#!/bin/bash
LOG=/var/log/myscipt.log
if [ ! -f ${LOG} ]; then
touch ${LOG}
fi
Ngoài ra bạn cũng có thể dùng câu rút gọn như sau.
[ ! -f $LOG ] && touch $LOG
Lưu ý: Nếu bạn không kiểm tra mà xử lý luôn trên file thì có thể dẫn đến việc script sẽ stop vì nó ko tìm thấy được
file mà bạn cần xử lý.
Tương tự với việc tìm file như VD trên, ta chỉ thay thể ký tự “f” bằng “d”, nó sẽ như phía dưới.
if [ -d <vị trí của directory> ]; then
<câu lệnh khi có directory có tồn tại>
else
<câu lệnh khi không có directory tồn tại>
fi
Giờ chỉ cần thêm ký tự “!” để kêu hàm trả về true khi directory không tồn tại, VD: Tạo directory “/tmp/test” nếu
không có sẵn
#!/bin/bash
TEST_PATH=/tmp/test
if [ ! -d ${TEST_PATH} ]; then
mkdir ${TEST_PATH}
fi
LƯU Ý: tránh tuyệt đối đặt tên biến là “PATH” nếu không thì nó sẽ ảnh hưởng đến các bin và sbin PATH, vì PATH là
biến lưu environment mặc định. Bạn có thể thử bằng câu lệnh sau.
# echo $PATH
Tuy nhiên ở 1 số trường hợp thì câu lệnh kết quả trả về là “null”, điều sẽ ảnh hưởng đển script, thế nên ta nên kiểm
tra xem biến có giá trị gì hay không.
3
Lưu ý: Trong dev giá trị 0 vẫn là 1 giá trị, “null” đồng nghĩa là không có giá trị.
VD, ta kết hợp với câu lệnh lấy vị trí hiện tại như trên:
#!/bin/bash
RESULT=$(pwd)
if [ -v “$RESULT” ]; then
echo “Path is not exist!”
else
echo $RESULT
fi
Với biến có giá trị rồi thì ta chỉ cần dùng so sánh giữa Biến với giá trị.
if [ $<tên biến> <so sánh> <giá trị muốn so sánh> ]; then
<câu lệnh thực hiện nếu kết quả là TRUE>
fi
Trên là những gì mà bạn cần quan tâm khi so sánh biến hoặc kiểm tra biến.
Cách đơn giản nhất là tìm các key words trong chuỗi ký tự, VD: Ta có 1 chuỗi 'GNU/Linux is an operating system'
và dùng keyword là ‘Linux’, vậy ta sẽ so sánh xem trong chuỗi có keyword hay không, nếu có thì trả về true, trong
script sẽ như sau.
#!/bin/bash
Vẫn có các cách khác nhau để tìm keyword trong chuỗi, bạn có thể Google để biết thêm chi tiết.
Tuy nhiên ta vẫn có cách ăn gian xíu, đó là thay vì so sánh chuỗi, ta sẽ chuyển nó về con số để dễ so sánh. Cụ thể
với VD trên, trước tiên ta chuyển thành số
# grep -e "$SUB" <<< "$STR" | wc -l
Giải thích:
4
1. grep -e sẽ tìm chuỗi SUB trong STR
2. wc -l sẽ đếm số dòng xuất hiện trên màn hình.
Như vậy, lệnh ‘grep -e "$SUB" <<< "$STR"’ sẽ xuất ra màn hình dòng STR vì nó có chứa SUB, sau đó wc sẽ đếm số
dòng xuất hiện, ở đây kết quả sẽ là 1. Thành ra nếu áp vào script thì nó sẽ như thế này.
#!/bin/bash
Trên là cách mà bạn có thể so sánh 2 chuỗi với nhau, vẫn còn có những cách khác, cách thực thi thì còn tùy thuộc
vào ý tường của bạn.
Looping.
Đối với vòng lặp, mình thường sử dụng “For” khi liên quan tới các mảng có giá trị rõ ràng, vì nó sẽ ít bước hơn và
do mảng có kết thúc so với “While”, thế nên sử dụng vòng lặp nào thì tùy thuộc vào thói quen của bạn mà thôi.
MY_PATH=/mnt/data
ITEMS=$(ls $MY_PATH)
MY_PATH=/mnt/data
ITEMS=$(ls $MY_PATH)
i=0
LEN=${#ITEMS[@]}
Như bạn có thể thấy là “FOR” nó ngắn hơn và cũng dễ hiểu hơn. Chú ý là cái này tùy từng người sẽ thích chọn
cách sử dụng, mình không nói là phải theo khuôn khổ của mình.
FILE=/mnt/data/test.txt
FILE=/mnt/data/test.txt
Cả 2 cách trên đều có sự tương đồng nhất định, bạn thích cách nào thì chọn cách đó nha.
Ví dụ.
Yêu cầu
Script có khả năng mã hóa và giải mã trong thư mục /mnt/data thỏa các điều kiện sau.
Scripting.
#!/bin/bash
# Biến khác
LOG=$DATA_PATH/info.log
KEY="abc@123"
if [ ! -d $DATA_PATH ]; then
echo "Data directory is not exist, please make sure it's there"
exit 1 # Thoát script nếu directory không tồn tại.
fi
if [ -v $FILE_NAME) ]; then
echo "The file name must be defined"
exit 1 # Thoát script khi tham số thứ 2 không tồn tại.
fi
if [ ! -d $ENC_PATH ]; then
mkdir $ENC_PATH # Tạo encrypt directory nếu không có
fi
if [ ! -d $DEC_PATH ]; then
mkdir $DEC_PATH # Tạo decrypt directory nếu không có
fi
FILE_PATH=$(find $DATA_PATH -type f -name "$FILE_NAME*") # Kiếm file trong thư mục
/mnt/data
6
if [ -v $FILE_PATH ]; then
echo "The file did not exists, exit now"
exit 1 # Thoát script khi file không tồn tại trong /mnt/data
fi
if [ ! -f $LOG ]; then
touch $LOG # Tạo file log nếu như không tồn tại.
fi
case "$OPTS_INFO" in
"enc")
openssl enc -aes256 -pbkdf2 -k "$KEY" -in $FILE_PATH -out
$ENC_PATH/$FILE_NAME.enc # Thực hiện việc mã hóa
rm -f $FILE_PATH # Bỏ file cũ sau khi đã được mã hóa
echo "$FILE_NAME was encrypted" | tee -a $LOG > /dev/null # Ghi vào log
thông báo việc mã hóa đã thành công.
;;
"dec")
if [ "$FILE_PATH" != ".enc"]; then
FILE_PATH=$FILE_PATH.enc # Thêm ký tự vào FILE_NAME nếu như tên không
chứa ký tự .enc
fi
openssl enc -aes256 -pbkdf2 -k "$KEY" -in $FILE_PATH -out
$DEC_PATH/$FILE_NAME # Thực hiện việc giải mã và lưa vào thư mục dec.
echo "$FILE_NAME was decrypted" | tee -a $LOG > /dev/null # Ghi vào log việc
giải mã file.
;;
*)
echo "There is no options here." # Thông báo script không có tham số thứ 1
và thoát khỏi script.
exit 1
;;
esac
Lưu ý: Bản script trên không hoàn toàn cover hết những bug mà nó sẽ gặp phải, script này chỉ có tác dụng cho bạn
nắm được cách thức hoạt động cơ bản của script.
Tổng kết.
Bài viết này mong có thể giúp bạn bắt đầu trong việc viết script, với mình thì scripting là không thể thiếu để mình
có thể dành thời gian làm những việc khác thay vì làm 1 việc nhiều lần.
NHÃ PHẠM