Hí mọi người lâu giờ mình cũng tiếp xúc với bash shell nhiều mà cũng chưa đi sâu hay tìm hiểu theo hệ thống nên loạt bài này mình sẽ đi theo hệ thống để biết nhiều thứ hơn về bash shell. Mọi người nếu ai mới tiếp cận môn này thì cùng tìm hiểu với mình nhé
1. Bắt đầu với Bash
1.1 Hello World
Bắt đầu thì chắc chứ làm phát "Hello World" cái nhở
echo "Hello World"
#> Hello World # Output Example
Interactive Shell
Cách trên được gọi là kiểu sử dụng interactively
: Nó cho phép bạn nhập và chỉnh sửa các lệnh, sau đó thực thi chúng khi bạn nhấn phím Return. Nhiều hệ điều hành dựa trên Unix và giống Unix sử dụng Bash làm trình bao mặc định của chúng (đặc biệt là Linux và macOS)
Non-Interactive Shell
Bash shell cũng có thể được chạy non-interactively
script, làm cho shell không cần sự tương tác của con người. Hành vi tương tác và hành vi theo tập lệnh phải giống hệt nhau . Vì vậy một cân nhắc thiết kế quan trọng của Unix V7 Bourne shell và tạm dịch là Bash. Nó đã làm cho bất cứ điều gì có thể được thực hiện tại dòng lệnh đều có thể được đưa vào một tệp script để sử dụng lại.
Cách sử dụng Non-Interactive Shell
theo các bước sau:
- Tạo một file ví dụ như hello-world.sh
touch hello-world.sh
- Chỉnh sửa file mới tạo Bạn có thể chỉnh sửa bằng 1 editor của hệ điều hành bạn đang dùng và chèn bash script bạn muốn chạy, ví dụ:
#!/bin/bash
echo "Hello World"
Note: Dòng đầu tiên của tập lệnh phải bắt đầu bằng chuỗi ký tự # !, được gọi là shebang1. Shebang hướng dẫn hệ điều hành chạy \bin bash
, Bash shell, truyền cho nó đường dẫn của script như một đối số. nó tương tự như /bin/bash hello-world.sh
- Cấp quyền excute cho nó
chmod +x hello-world.sh
- Chạy file. Để chạy file bạn có thể làm một vài cách sau
./hello-world.sh # most commonly used, and recommended
/bin/bash hello-world.sh
bash hello-world.sh # assuming /bin is in your $PATH
sh hello-world.sh
1.2 Cũng là Hello World nhưng học thêm với biến nhé
Hãy tạo một một file hello.sh
và cấp quyền excute cho nó nhé chmod +x hello.sh.
Sau đó thêm script này vào
#!/usr/bin/env bash
# Note that spaces cannot be used around the `=` assignment operator
whom_variable="World"
# Use printf to safely output the data
printf "Hello, %s\n" "$whom_variable"
#> Hello, World
Các bạn có thể thấy kết quả in ra sau khi chạy là Hello, World. Vì vậy có thể thấy rằng 'World' đã được gán vào whom_variable
, đây cũng là cách sửa dụng biến trong bash, Tuy nhiên hãy lưu ý điều này nhé: Không thể sử dụng dấu cách xung quanh toán tử gán =
Đoạn mã sau chấp nhận một đối số $1, là đối số dòng lệnh đầu tiên và nó được in ra trong một chuỗi được định dạng, phía sau "Hello,". Hãy sửa hello.sh thành thế này
#!/usr/bin/env bash
printf "Hello, %s\n" "$1"
#> Hello, World
sau đó chạy ./hello.sh World
Kết quả sẽ là Hello, World
bạn có thể thấy 'World' đã được truyền vào $1, sau này khi làm bạn cũng có thể truyền thêm nhiều tham số nữa ./hello.sh World World2 World3
chả hạn, tuy nhiên muốn lấy giá trị 'Word2' 'World3' bạn phải sử dụng đến $2
, $3
1.3 Cũng là Hello World nhưng với User Input
Phần này mình sẽ tiếp cận theo cách răng: sẽ nhắc người dùng nhập vào một giá trị, sau đó sẽ gán chuỗi đó vào một biến và in biến đó ra.
Ví dụ:
#!/usr/bin/env bash
echo "Who are you?"
read name
echo "Hello, $name."
Output:
$ ./hello_world.sh
Who are you?
Matt
Hello, Matt.
Lệnh read
ở đây đọc một dòng dữ liệu từ đầu vào chuẩn vào tên biến. Sau đó, điều này được tham chiếu bằng cách sử dụng $name và được in ra chuẩn bằng cách sử dụng echo.
Và nếu bạn muốn nối một thứ gì đó vào giá trị biến trong khi in nó, hãy sử dụng dấu ngoặc nhọn xung quanh tên biến như được hiển thị trong ví dụ sau:
#!/usr/bin/env bash
echo "What are you doing?"
read action
echo "You are ${action}ing."
Ouput:
$ ./hello_world.sh
What are you doing?
Sleep
You are Sleeping.
1.4 Tầm quan trọng của Quoting trong Strings
Quoting rất quan trọng đối với việc mở rộng chuỗi trong bash. Với những thứ này, bạn có thể kiểm soát cách bash phân tích cú pháp và mở rộng chuỗi của bạn.
- Weak: dùng double quotes: "
- Strong: dùng single quotes: '
Nếu bạn muốn bash mở rộng đối số của mình, bạn có thể sử dụng Weak Quoting:
#!/usr/bin/env bash
world="World"
echo "Hello $world"
#> Hello World
Nếu bạn không muốn bash mở rộng đối số của mình, bạn có thể sử dụng Strong Quoting:
#!/usr/bin/env bash
world="World"
echo 'Hello $world'
GoalKicker.com – Bash Notes for Professionals 6
#> Hello $world
Bạn cũng có thể sử dụng escape để ngăn expansion:
#!/usr/bin/env bash
world="World"
echo "Hello \$world"
#> Hello $world
1.5 Xem thông tin Bash built-ins (cũng như đọc DOC vậy)
Cú pháp sẽ đi kèm từ khóa help
help <command>
Ví dụ sử dụng help unset
sẽ hiển thị:
unset: unset [-f] [-v] [-n] [name ...]
Unset values and attributes of shell variables and functions.
For each NAME, remove the corresponding variable or function.
Options:
-f treat each NAME as a shell function
-v treat each NAME as a shell variable
-n treat each NAME as a name reference and unset the variable itself
rather than the variable it references
Without options, unset first tries to unset a variable, and if that fails,
tries to unset a function.
Some variables cannot be unset; also see `readonly'.
Exit Status:
Returns success unless an invalid option is given or a NAME is read-only.
Để xem danh sách tất cả các cài đặt sẵn với mô tả ngắn gọn, hãy sử dụng:
help -d
1.6 Hello World trong "Debug" mode
$ cat hello.sh
#!/bin/bash
echo "Hello World"
$ bash -x hello.sh
+ echo Hello World
Hello World
Đối số -x cho phép bạn xem qua từng dòng trong tập lệnh. Một ví dụ nè:
Cái này là chưa dùng -x nhé
$ cat hello.sh
#!/bin/bash
echo "Hello World\n"
adding_string_to_number="s"
v=$(expr 5 + $adding_string_to_number)
Chạy nè
$ ./hello.sh
Output
Hello World
expr: non-integer argument
Lỗi ở trên không đủ để theo dõi tập lệnh; tuy nhiên, sử dụng cách sau sẽ giúp bạn hiểu rõ hơn về nơi bị lỗi trong tập lệnh.
Còn dùng -x thì sao
Vẫn hơi giống cái trên nhưng thêm -x nè
$ bash -x hello.sh
Output
+ echo Hello World\n
Hello World
+ adding_string_to_number=s
+ expr 5 + s
expr: non-integer argument
+ v=
Bạn có thể thấy lỗi ở đâu và việc còn lại là đi sửa thôi phải không =))
2. Script shebang
2.1 Env shebang
Để thực thi một script file với bash executable được tìm thấy trong biến môi trường PATH bằng cách sử dụng executable
env
, dòng đầu tiên của script file bản phải chỉ ra đường dẫn tuyệt đối đến tệp thực thi env với đối số bash:
#!/usr/bin/env bash
Đường dẫn env trong shebang được giải quyết và chỉ được sử dụng khi một tập lệnh được khởi chạy trực tiếp như sau:
script.sh
Script phải có quyền thực thi. Shebang bị bỏ qua khi một trình thông dịch bash được chỉ định rõ ràng để thực thi một tập lệnh:
bash script.sh
2.2 Direct shebang
Để thực thi một script file với trình thông dịch bash, dòng đầu tiên của script file phải chỉ ra đường dẫn tuyệt đối đến tệp thực thi bash để sử dụng:
#!/bin/bash
Đường dẫn bash trong shebang được giải quyết và chỉ được sử dụng nếu một script file được khởi chạy trực tiếp như sau:
./script.sh
Script phải có quyền thực thi. Shebang bị bỏ qua khi một trình thông dịch bash được chỉ định rõ ràng để thực thi một tập lệnh:
bash script.sh
3. Navigating directories
3.1: Absolute vs relative directories
Để thay đổi thành một thư mục được chỉ định hoàn toàn, hãy sử dụng toàn bộ tên, bắt đầu bằng dấu gạch chéo
cd /home/username/project/abc
Nếu bạn muốn thay đổi đến một thư mục nằm trong thư mục hiện tại bạn đang ở đấy, bạn có thể chỉ định một vị trí tương đối. Ví dụ: nếu bạn đã ở /home/username/project
và bạn có một thư mục xyz ở trong thư mục đó. Nêu muốn thay đổi đến xyz bạn chỉ cần sử dụng
cd xyz
Nếu bạn muốn đi đến thư mục phía trên thư mục hiện tại, bạn có thể sử dụng bí danh ..
. Ví dụ: nếu bạn ở /home/username/project/xyz
và muốn đến /home/username/project
, thì bạn hãy sử dụng:
cd ..
Điều này cũng có thể được gọi là "lên" một thư mục.
3.2: Chuyển đến thư mục gần nhất bạn ở đó
Đối với trình bao hiện tại, điều này sẽ đưa bạn đến thư mục trước đó mà bạn đã ở đó, bất kể nó ở đâu.
cd -
Làm điều đó nhiều lần có hiệu quả sẽ "chuyển" bạn đang ở trong thư mục hiện tại hoặc thư mục trước đó.
3.3 Chuyển đến thư mục home
Thư mục mặc định là thư mục chính ($HOME, thường là /home/username), vì vậy nếu bạn chỉ sử dụng mình cd
sẽ đưa bạn đến đó
cd
Hoặc bạn có thể rõ ràng hơn:
cd $HOME
Một phím tắt cho thư mục home là ~, vì vậy cũng có thể được sử dụng.
cd ~
Ví dụ như ở máy của mình
4. Listing Files
Option | Description |
---|---|
-a, --all | Liệt kê tất cả các mục bao gồm những mục . và .. |
-A, --almost-all | Liệt kê tất cả các mục trừ mục . và .. |
-c | Sắp xếp các file theo thời gian thay đổi |
-d, --directory | Danh sách chỉ gồm các folder |
-h, --human-readable | Hiển thị kích thước ở định dạng con người có thể đọc được (tức là K, M) (đi kèm option s ví dụ -sh ) |
-H | Tương tự như trên nhưng với tỉ lệ quy đổi là 1000 thay vì 1024 |
-l | Hiển thị nội dung với định dạng long-listing |
-o | Long -listing format nhưng không có thông tin group |
-r, --reverse | HIển thị nội dung nhưng với sự sắp xếp ngược lại |
-s, --size | Danh sách cách tệp với kích thước của từng thành phần |
-S | Sắp xếp theo kích thước file |
--sort=WORD | Sắp xếp danh sahcs file theo từ khóa, ví dụ: size, version,status |
-t | Sắp xếp theo thời gian sửa đổi |
-u | Sắp xếp theo thời gian truy cập |
-v | Sắp xếp theo version |
-1 | Danh sách nhưng với 1 file một dòng |
4.1 Danh sách các tệp ở định dạng Long Listing
Tùy chọn -l của lệnh ls in nội dung của thư mục cụ thể ở định dạng Long Listing. Nếu không có thư mục nào được chỉ định thì theo mặc định, nội dung của thư mục hiện tại sẽ được liệt kê.
ls -l /etc
Output mẫu:
total 1204
drwxr-xr-x 3 root root 4096 Apr 21 03:44 acpi
-rw-r--r-- 1 root root 3028 Apr 21 03:38 adduser.conf
drwxr-xr-x 2 root root 4096 Jun 11 20:42 alternatives
...
Đầu tiên hiển thị tổng số, cho biết tổng kích thước tính bằng khối của tất cả các tệp trong thư mục được liệt kê. Sau đó, nó hiển thị tám cột thông tin cho mỗi tệp trong thư mục được liệt kê. Dưới đây là chi tiết cho từng cột trong đầu ra:
Column No. | Example | Description |
---|---|---|
1.1 | d | File type (xem ở bảng dưới đây) |
1.2 | rwxr-xr-x | Permission string |
2 | 3 | Number of hard links |
3 | root | Owner name |
4 | root | Owner group |
5 | 4096 | File size in bytes |
6 | Apr 21 03:44 | Modification time |
7 | acpi | File name |
File type có thể là một trong bất kỳ ký tự nào sau đây.
Character | File Type |
---|---|
- | Regular file |
b | Block special file |
c | Character special file |
C | High performance ("contiguous data") file |
d | Directory |
D | Door (special IPC file in Solaris 2.5+ only) |
l | Symbolic link |
M | Off-line ("migrated") file (Cray DMF) |
n | Network special file (HP-UX) |
p | FIFO (named pipe) |
P | Port (special system file in Solaris 10+ only) |
s | Socket |
? | Some other file type |
4.2 Danh sách 10 File được thay đổi gần đây nhất
Phần sau sẽ liệt kê tối đa mười tệp được sửa đổi gần đây nhất trong thư mục hiện tại, sử dụng long listing format (-l) và được sắp xếp theo thời gian (-t).
ls -lt | head
Note: Với head
mặc định nếu bạn không truyền tham số thì sẽ lấy là kết quả là 10 dòng đầu tiên, tuy nhiên bạn có thể dùng option để có thể lấy nhiều hoặc ít hơn, vi dụ: ls -lt | head -20
4.3 List File với Dotfiles
Dotfile là một tệp có tên bắt đầu bằng dấu chấm .
Chúng thường được ẩn bởi ls và không được liệt kê trừ khi được yêu cầu.
Ví dụ:
$ ls
bin pki
Option -a hoặc --all sẽ lấy ra tất cả các file bao gồm dotfiles
$ ls -a
. .ansible .bash_logout .bashrc .lesshst .puppetlabs .viminfo
.. .bash_history .bash_profile bin pki .ssh
Option -A hoặc --almost-all sẽ liệt kê sánh sách tát cả các file, bao gồm cả dotfile tuy nhiên sẽ không bao gồm .
và ..
. Bạn đang tự hỏi .
. và ..
là gì phải không?
Câu trả lời đây nhé: .
là thư mục hiện tại và ..
là thư mục cha của nó.
$ ls -A
.ansible .bash_logout .bashrc .lesshst .puppetlabs .viminfo
.bash_history .bash_profile bin pki .ssh
4.4 Danh sách các file nhưng không dùng ls
Bạn hoàn toàn có thể sử dụng khả năng Filename Expansion và brace expansion của BashShell để lấy các file.
# display the files and directories that are in the current directory
printf "%s\n" *
# display only the directories in the current directory
printf "%s\n" */
# display only (some) image files
printf "%s\n" *.{gif,jpg,png}
Để lưu danh sách các tệp thành một biến để xử lý, thông thường bạn nên sử dụng bash array:
files=( * )
# iterate over them
for file in "${files[@]}"; do echo "$file"
done
4.6 Danh sách các file dạng tree
tree
command sẽ lấy ra danh sách các file trong một thư mục được chỉ định ra dưới dạng tree
Ví dụ:
$ tree /tmp
/tmp
├── 5037
├── adb.log
└── evince-20965 └── image.FPWTJY.png
Sử dụng tùy chọn -L của lệnh tree để giới hạn độ sâu hiển thị và tùy chọn -d để chỉ liệt kê các thư mục. Ví dụ
$ tree -L 1 -d /tmp
/tmp
└── evince-20965
5. Sử dụng cat
To be continue...
Tham khảo
Bạn có thể đọc nội dung trên ở: