103.1 Bài 2
[[.fronttable,cols="h,"]
Chứng chỉ: |
LPIC-1 |
Phiên bản: |
5.0 |
Chủ đề: |
103 Lệnh GNU và Unix |
Mục tiêu: |
103.1 Làm việc trên Dòng lệnh |
Bài: |
2 trên 2 |
Giới thiệu
Môi trường hệ điều hành bao gồm các công cụ cơ bản — như vỏ dòng lệnh và đôi khi là GUI — mà ta sẽ cần đến để hoàn thành các tác vụ. Tuy nhiên, môi trường cũng sẽ có một danh mục các phím tắt và giá trị được thiết lập sẵn đi kèm với nó. Bài học này là nơi chúng ta sẽ tìm hiểu về cách liệt kê, gọi và quản lý các giá trị đó.
Tìm các Biến Môi trường
Vậy làm cách nào để chúng ta xác định các giá trị hiện tại cho từng biến môi trường? Có một cách là thông qua lệnh env
:
$ env DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus XDG_RUNTIME_DIR=/run/user/1000 XAUTHORITY=/run/user/1000/gdm/Xauthority XDG_CONFIG_DIRS=/etc/xdg/xdg-ubuntu:/etc/xdg PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin GJS_DEBUG_TOPICS=JS ERROR;JS LOG [...]
Ta sẽ nhận được rất nhiều kết quả — nhiều hơn cả trong đoạn trích trên. Nhưng hãy lưu ý mục nhập PATH
đang chứa các thư mục mà vỏ (và các chương trình khác) sẽ tìm kiếm các chương trình khác mà không cần phải chỉ định một đường dẫn chi tiết. Từ đó, ta có thể chạy một chương trình nhị phân (giả sử là ở trong /usr/local/bin
từ trong thư mục chính và nó sẽ chạy như thể tệp là cục bộ).
Hãy thay đổi chủ đề một chút. Lệnh echo
sẽ in ra màn hình bất cứ thứ gì chúng ta yêu cầu. Dù có tin hay không, có nhiều lúc việc sử dụng echo
để lặp lại điều gì đó theo đúng nghĩa đen sẽ rất hữu ích.
$ echo "Hi. How are you?" Hi. How are you?
Nhưng ta cũng có thể thực hiện một tác vụ khác với echo
. Khi ta cung cấp cho nó tên của một biến môi trường — và nói với nó rằng đây là một biến bằng cách thêm $
vào trước tên biến — và sau đó, thay vì chỉ in tên của biến, vỏ sẽ mở rộng nó để cung cấp giá trị cho chúng ta. Nếu đang tự hỏi liệu thư mục yêu thích hiện có trong đường dẫn hay không, người dùng có thể nhanh chóng kiểm tra bằng cách chạy nó qua echo
:
$ echo $PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
Tạo các Biến Môi trường mới
Chúng ta có thể thêm các biến tùy chỉnh của riêng mình vào môi trường. Cách đơn giản nhất là sử dụng ký tự =
. Chuỗi bên trái sẽ là tên của biến mới và chuỗi bên phải sẽ là giá trị của nó. Bây giờ, ta có thể cung cấp tên biến cho echo
để xác nhận rằng nó đã hoạt động:
$ myvar=hello $ echo $myvar hello
Note
|
Hãy lưu ý rằng sẽ không có khoảng trống ở hai bên của dấu bằng trong quá trình gán biến. |
Nhưng nó có thực sự hoạt động hay không? Hãy nhập bash
vào cửa sổ dòng lệnh để mở vỏ mới. Vỏ mới này trông giống hệt như vỏ ta vừa sử dụng, nhưng thực chất nó chính là con của vỏ ban đầu (tức vỏ mẹ). Bây giờ, bên trong vỏ con mới này, hãy thử để echo
thực hiện công việc của nó theo cách nó đã làm trước đây. Nhưng lại không có gì xảy ra. Lý do là gì?
$ bash $ echo $myvar $
Biến được tạo theo cách chúng ta vừa làm sẽ chỉ khả dụng cục bộ — tức là trong phiên vỏ tại thời điểm đó. Nếu khởi động một vỏ mới — hoặc đóng phiên bằng lệnh exit
— biến sẽ không tiếp tục hoạt động. Việc nhập exit
ở đây sẽ đưa ta trở lại vỏ gốc ban đầu, tức là chúng ta đang cần phải đến. Ta có thể chạy echo $myvar
một lần nữa nếu muốn xác nhận rằng biến vẫn hợp lệ. Bây giờ, hãy nhập export myvar
để chuyển biến cho bất kỳ vỏ con nào mà ta sẽ mở sau đó. Hãy thử nhập bash
để có vỏ mới và sau đó nhập echo
:
$ exit $ export myvar $ bash $ echo $myvar hello
Tất cả những điều này nghe có vẻ hơi ngớ ngẩn khi chúng ta đang tạo ra các vỏ không có mục đích thực sự. Tuy vậy, việc hiểu cách các biến vỏ được truyền qua hệ thống sẽ trở nên rất quan trọng khi chúng ta bắt đầu viết các tệp lệnh quan trọng.
Xóa các Biến Môi trường
Làm thế nào để dọn sạch tất cả các biến tạm thời mà mình đã tạo? Một cách đơn giản là đóng vỏ gốc — hoặc khởi động lại máy tính. Nhưng cũng có nhiều cách đơn giản hơn, chẳng hạn như unset
. Việc nhập unset
(không có $
) sẽ loại bỏ biến. echo
sẽ chứng minh điều đó ngay bây giờ.
$ unset myvar $ echo $myvar $
Nếu đã có lệnh unset
thì đương nhiên sẽ phải có một lệnh set
đi cùng với nó. Việc chạy riêng lệnh set
sẽ hiển thị nhiều đầu ra, nhưng nó thực sự không khác mấy so với những gì env
đã cung cấp. Hãy nhìn vào dòng đầu ra đầu tiên khi lọc PATH
:
$ set | grep PATH PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin [...]
Sự khác biệt giữa set
và env
là gì? Đối với mục đích của chúng ta, việc trọng yếu là set
sẽ xuất ra tất cả các biến và hàm. Hãy cùng minh họa điều này. Chúng ta sẽ tạo một biến mới gọi là mynewvar
và sau đó xác nhận rằng nó đang ở đó:
$ mynewvar=goodbye $ echo $mynewvar goodbye
Bây giờ, việc chạy env
trong khi sử dụng grep
để lọc chuỗi mynewvar
sẽ không hiển thị bất kỳ đầu ra nào. Nhưng nếu chạy set
theo cùng một cách thì ta sẽ thấy được biến cục bộ.
$ env | grep mynewvar $ set | grep mynewvar mynewvar=goodbye
Trích dẫn để thoát các Ký tự Đặc biệt
Bây giờ là thời điểm tốt nhất để giới thiệu tới bạn các vấn đề về ký tự đặc biệt. Các ký tự chữ và số (a-z và 0-9) thường sẽ được Bash đọc theo nghĩa đen. Nếu muốn tạo một tệp mới có tên myfile
, ta chỉ cần nhập touch
, theo sau là myfile
và Bash sẽ biết phải làm gì với nó. Nhưng nếu muốn bao gồm một ký tự đặc biệt trong tên tệp của mình, chúng ta sẽ cần thực hiện thêm một số thao tác.
Để minh họa điều này, chúng ta sẽ nhập touch
và theo sau là tiêu đề: my big file
. Vấn đề ở đây là có hai khoảng trắng giữa các từ mà Bash sẽ diễn giải. Mặc dù về mặt kỹ thuật thì một khoảng trắng không được coi là một “ký tự” nhưng nó lại giống như một ký tự bởi Bash sẽ không đọc nó theo nghĩa đen. Nếu liệt kê nội dung của thư mục hiện tại, thay vì một tệp có tên my big file
, chúng ta sẽ thấy ba tệp có tên tương ứng là my
, big
và file
. Đó là bởi vì Bash nghĩ rằng người dùng muốn tạo nhiều tệp với các từ được liệt kê:
$ touch my big file $ ls my big file
Các khoảng trắng cũng sẽ được diễn giải theo cách này nếu chúng ta muốn xóa (rm
) cả ba tệp trong một lệnh:
$ rm my big file
Bây giờ, chúng ta hãy thử thực hiện đúng cách. Hãy nhập touch
và ba phần tên tệp, nhưng lần này, hãy đặt tên tệp trong dấu trích dẫn kép. Bây giờ thì nó đã hoạt động đúng như mong đợi. Việc liệt kê nội dung thư mục sẽ hiển thị cho ta một tệp có tên chuẩn xác.
$ touch "my big file" $ ls 'my big file'
Có nhiều cách khác để có được kết quả tương tự. Ví dụ, dấu trích dẫn đơn cũng hoạt động giống như dấu trích dẫn kép (hãy lưu ý rằng dấu trích dẫn đơn sẽ giữ nguyên giá trị theo nghĩa đen của tất cả các ký tự, trong khi dấu trích dẫn kép sẽ giữ nguyên tất cả các ký tự ngoại trừ $
, `
, \
và, trong một số trường hợp nhất định, !
.)
$ rm 'my big file'
Nếu ta đặt trước mỗi ký tự đặc biệt một dấu gạch chéo ngược, nó sẽ “thoát” đi tính đặc biệt của ký tự và khiến Bash đọc nó theo đúng nghĩa đen.
$ touch my\ big\ file
Bài tập Hướng dẫn
-
Hãy sử dụng lệnh
export
để thêm một thư mục mới vào đường dẫn của bạn (thư mục này sẽ không tồn tại khi khởi động lại). -
Hãy sử dụng lệnh
unset
để xóa biếnPATH
. Hãy thử chạy một lệnh (nhưsudo cat /etc/shadow
) bằng cách sử dụngsudo
. Chuyện gì đã xảy ra? Tại sao? (Thoát khỏi vỏ sẽ đưa bạn trở lại trạng thái ban đầu.)
Bài tập Mở rộng
-
Hãy tìm kiếm trên internet và khám phá danh sách đầy đủ các ký tự đặc biệt.
-
Hãy thử chạy các lệnh bằng cách sử dụng các chuỗi gồm các ký tự đặc biệt và sử dụng các phương pháp khác nhau để thoát chúng. Có sự khác biệt giữa cách thức hoạt động của các phương pháp đó không?
Tóm tắt
Trong bài học này, chúng ta đã học về:
-
Cách xác định các biến môi trường của hệ thống.
-
Cách tạo các biến môi trường của riêng bạn và xuất chúng sang các vỏ khác.
-
Cách loại bỏ các biến môi trường và cách sử dụng cả hai lệnh
env
vàset
. -
Làm cách nào để thoát các ký tự đặc biệt để Bash đọc chúng theo nghĩa đen.
Các lệnh sau đã được thảo luận trong bài học này:
echo
-
In các chuỗi và biến đầu vào.
env
-
Hiểu và sửa đổi các biến môi trường.
export
-
Truyền một biến môi trường cho vỏ con.
unset
-
Bỏ thiết lập giá trị, thuộc tính của các biến vỏ và hàm.
Đáp án Bài tập Hướng dẫn
-
Hãy sử dụng lệnh
export
để thêm thư mục mới vào đường dẫn của bạn (thư mục này sẽ không tồn tại khi khởi động lại).Bạn có thể tạm thời thêm một thư mục mới (có thể là
myfiles
nằm trong thư mục chính) vào đường dẫn bằng cách sử dụngexport PATH="/home/yourname/myfiles:$PATH"
. Hãy tạo một tệp lệnh đơn giản trong thư mụcmyfiles/
, làm cho nó có thể thực thi được và thử chạy nó từ một thư mục khác. Các lệnh này sẽ giả định bạn đang ở trong thư mục chính có chứa thư mục tênmyfiles
.$ touch myfiles/myscript.sh $ echo '#!/bin/bash' >> myfiles/myscript.sh $ echo 'echo Hello' >> myfiles/myscript.sh $ chmod +x myfiles/myscript.sh $ myscript.sh Hello
-
Hãy sử dụng lệnh
unset
để xóa biếnPATH
. Hãy thử chạy một lệnh (nhưsudo cat /etc/shadow
) bằng cách sử dụngsudo
. Chuyện gì đã xảy ra? Tại sao? (Thoát khỏi vỏ sẽ đưa bạn trở lại trạng thái ban đầu.)Nhập
unset PATH
sẽ xóa cài đặt đường dẫn hiện tại. Việc cố gọi một chương trình nhị phân mà không có địa chỉ tuyệt đối sẽ không thành công. Vì lý do đó, việc cố gắng chạy một lệnh bằng sudo (bản thân nó là một chương trình nhị phân nằm trong/usr/bin/sudo
) sẽ không thành công — trừ khi bạn có chỉ định vị trí tuyệt đối (như trong:/usr/bin/sudo /bin/cat /etc/shadow
). Bạn có thể đặt lạiPATH
của mình bằng cách sử dụngexport
hoặc đơn giản là thoát khỏi vỏ.
Đáp án Bài tập Mở rộng
-
Hãy tìm kiếm trên internet và khám phá danh sách đầy đủ các ký tự đặc biệt.
Đây là danh sách các ký tự đặc biệt:
& ; | * ? " ' [ ] ( ) $ < > { } # / \ ! ~
. -
Hãy thử chạy các lệnh bằng cách sử dụng các chuỗi gồm các ký tự đặc biệt và sử dụng các phương pháp khác nhau để thoát chúng. Có sự khác biệt giữa cách thức hoạt động của các phương pháp đó không?
Việc thoát bằng cách sử dụng các ký tự
"
sẽ bảo toàn các giá trị đặc biệt của ký hiệu đô la ($), dấu đánh dấu ngược () và dấu gạch chéo ngược (\). Mặt khác, việc thoát bằng cách sử dụng ký tự ’
sẽ hiển thị tất cả các ký tự dưới dạng chữ.$ echo "$mynewvar" goodbye $ echo '$mynewvar' $mynewvar