Mỗi nghề đều có công cụ mà các bậc thầy trong nghề đó sử dụng nhiều nhất. Đối với nhiều sysadmin, công cụ đó chính là shell của họ. Trên hầu hết các hệ thống Linux và các hệ thống Unix-like khác, shell mặc định là Bash.
Bash là một chương trình khá cũ—xuất hiện vào cuối những năm 1980—nhưng nó xây dựng dựa trên các shell cũ hơn nhiều, như C shell (csh), lớn hơn nó 10 năm. Vì khái niệm shell đã lâu đời như vậy, nên có một lượng kiến thức bí ẩn khổng lồ đang chờ đợi để được tiêu thụ, giúp cuộc sống của bất kỳ sysadmin nào dễ dàng hơn rất nhiều.
Hãy cùng xem xét một số kiến thức cơ bản.
Ai đã từng vô tình chạy một lệnh với quyền root và gây ra sự cố? giơ tay
Tôi chắc chắn rất nhiều người trong chúng ta đã từng là "người đó" tại một thời điểm nào đó. Rất đau đớn. Dưới đây là một số mẹo rất đơn giản để ngăn chặn việc bạn vấp phải cùng một tảng đá lần thứ hai.
Sử dụng alias
Trước tiên, hãy thiết lập alias cho các lệnh như mv và rm trỏ đến mv -i và rm -i. Điều này đảm bảo việc chạy rm -f /boot ít nhất sẽ yêu cầu xác nhận. Trong Red Hat Enterprise Linux, các alias này được thiết lập mặc định nếu bạn dùng tài khoản root.
Nếu bạn muốn thiết lập các alias đó cho tài khoản người dùng bình thường, chỉ cần thêm hai dòng sau vào file .bashrc trong thư mục home (các alias này cũng hoạt động với sudo):
alias mv='mv -i'
alias rm='rm -i'
Làm cho dấu nhắc root nổi bật
Một việc khác bạn có thể làm để ngăn chặn sự cố là đảm bảo bạn nhận ra khi đang dùng tài khoản root. Thông thường tôi làm điều đó bằng cách làm cho dấu nhắc root nổi bật rõ rệt so với dấu nhắc dùng cho công việc hàng ngày.
Nếu bạn thêm đoạn sau vào file .bashrc trong thư mục home của root, bạn sẽ có dấu nhắc root màu đỏ trên nền đen, khiến ai đó (bao gồm cả bạn) phải thận trọng.
export PS1="\[$(tput bold)$(tput setab 0)$(tput setaf 1)\]\u@\h:\w # \[$(tput sgr0)\]"
Thực tế, bạn nên tránh đăng nhập bằng root nhiều nhất có thể và thay vào đó chạy hầu hết lệnh sysadmin qua sudo, nhưng đó là chuyện khác.
Sau khi triển khai một vài mẹo nhỏ giúp ngăn chặn "tác dụng phụ không mong muốn" của việc dùng tài khoản root, hãy xem vài điều hay mà Bash giúp bạn làm trong công việc hàng ngày.
Kiểm soát lịch sử lệnh
Bạn có thể biết rằng khi nhấn phím mũi tên lên trong Bash, bạn có thể xem và tái sử dụng tất cả (vâng, rất nhiều) lệnh trước đó. Đó là vì các lệnh đó đã được lưu vào file .bash_history trong thư mục home. File lịch sử đó đi kèm với một loạt cài đặt và lệnh rất hữu ích.
Trước hết, bạn có thể xem toàn bộ lịch sử lệnh gần đây bằng cách gõ history, hoặc giới hạn 30 lệnh gần nhất bằng history 30. Nhưng đó vẫn cơ bản. Bạn có thêm quyền kiểm soát việc Bash lưu gì và lưu như thế nào.
Ví dụ, nếu bạn thêm sau vào .bashrc, bất kỳ lệnh nào bắt đầu bằng dấu cách sẽ không được lưu vào danh sách lịch sử:
HISTCONTROL=ignorespace
Điều này hữu ích nếu bạn cần truyền mật khẩu cho một lệnh dưới dạng văn bản thuần túy. (Vâng, đó là việc tồi tệ, nhưng nó vẫn xảy ra.)
Nếu bạn không muốn một lệnh thường xuyên thực hiện xuất hiện trong lịch sử, hãy dùng:
HISTCONTROL=ignorespace:erasedups
Với thiết lập này, mỗi khi bạn dùng một lệnh, tất cả các lần xuất hiện trước đó của nó sẽ bị xóa khỏi file lịch sử, và chỉ lần gọi gần nhất được lưu.
Một cài đặt lịch sử tôi đặc biệt thích là HISTTIMEFORMAT. Cài đặt này sẽ thêm dấu thời gian vào đầu tất cả các mục trong file lịch sử. Ví dụ, tôi dùng:
HISTTIMEFORMAT="%F %T "
Khi tôi gõ history 5, tôi nhận được thông tin đầy đủ, đẹp mắt, như sau:
1009 2018-06-11 22:34:38 cat /etc/hosts
1010 2018-06-11 22:34:40 echo $foo
1011 2018-06-11 22:34:42 echo $bar
1012 2018-06-11 22:34:44 ssh myhost
1013 2018-06-11 22:34:55 vim .bashrc
Điều đó giúp duyệt lịch sử lệnh và tìm lệnh tôi dùng hai ngày trước để thiết lập đường hầm SSH đến lab tại nhà (lệnh mà tôi quên đi, và quên đi, và quên đi…).
Các thực hành tốt nhất với Bash
Tôi sẽ kết thúc với danh sách top 11 các thực hành tốt (hoặc khá tốt, tôi không tự nhận là biết hết) khi viết script Bash.
-
Script Bash có thể trở nên phức tạp và chú thích rất "rẻ". Nếu bạn thắc mắc có nên thêm chú thích, hãy thêm. Nếu sau cuối tuần bạn quay lại và phải mất thời gian để tìm ra mình đang cố làm gì vào thứ Sáu trước, nghĩa là bạn quên thêm chú thích.
- Bọc tất cả tên biến trong ngoặc nhọn, như
${myvariable}. Làm thói quen này làm cho các thứ như${variable}_suffixtrở nên khả thi và cải thiện tính nhất quán trong suốt script.
- Không dùng backtick khi đánh giá biểu thức; hãy dùng cú pháp
$()thay thế. Vậy hãy dùng:
for file in $(ls); dothay vì
for file in `ls`; doCú pháp trước có thể lồng nhau, dễ đọc hơn, và làm hài lòng cộng đồng sysadmin nói chung. Đừng dùng backtick.
- Tính nhất quán là tốt. Chọn một phong cách làm việc và kiên trì với nó xuyên suốt script. Tất nhiên, tôi thích nếu mọi người chọn cú pháp
$()thay vì backtick và bọc biến trong ngoặc nhọn. Tôi thích nếu mọi người dùng hai hoặc bốn dấu cách—không phải tab—để thụt lề, nhưng ngay cả khi bạn chọn cách sai, hãy sai một cách nhất quán.
- Dùng shebang thích hợp cho script Bash. Vì tôi viết script Bash với ý định chỉ chạy bằng Bash, tôi thường dùng
#!/usr/bin/bashlàm shebang. Đừng dùng#!/bin/shhoặc#!/usr/bin/sh. Script vẫn chạy, nhưng sẽ ở chế độ tương thích—có thể gây nhiều tác dụng phụ không mong muốn. (Trừ khi bạn thực sự muốn chế độ tương thích.)
- Khi so sánh chuỗi, tốt nhất là đặt biến trong ngoặc kép trong câu lệnh if, vì nếu biến rỗng, Bash sẽ báo lỗi cho các dòng như:
if [ ${myvar} == "foo" ]; then
echo "bar"
fiVà sẽ đánh giá là false cho dòng như sau:
if [ "${myvar}" == "foo" ]; then
echo "bar"
fiNgoài ra, nếu bạn không chắc về nội dung biến (ví dụ khi phân tích đầu vào người dùng), hãy đặt biến trong ngoặc kép để ngăn chặn việc thông dịch một số ký tự đặc biệt và đảm bảo biến được coi như một từ đơn, ngay cả khi nó chứa khoảng trắng.
- Đây là vấn đề sở thích, nhưng tôi thích dùng dấu bằng kép (
==) ngay cả khi so sánh chuỗi trong Bash. Đó là vấn đề nhất quán, và dù—chỉ cho so sánh chuỗi—dấu bằng đơn cũng hoạt động, nhưng đầu tôi ngay lập tức nghĩ "dấu bằng đơn là toán tử gán!".
- Dùng mã thoát thích hợp. Đảm bảo nếu script thất bại, bạn hiển thị thông báo lỗi bằng văn bản (tốt nhất kèm cách khắc phục) và trả về mã thoát khác 0:
# we have failed
echo "Process has failed to complete, you need to manually restart the whatchamacallit"
exit 1Điều này giúp dễ dàng gọi script từ script khác và xác minh việc hoàn thành thành công.
- Sử dụng cơ chế tích hợp của Bash để cung cấp giá trị mặc định hợp lý cho biến hoặc báo lỗi nếu biến bạn mong đợi được định nghĩa nhưng không:
# this sets the value of $myvar to redhat, and prints 'redhat'
echo ${myvar:=redhat}# this throws an error reading 'The variable myvar is undefined, dear reader' if $myvar is undefined
${myvar:?The variable myvar is undefined, dear reader}
- Đặc biệt nếu bạn viết script lớn, và đặc biệt nếu làm việc trên script đó với người khác, hãy cân nhắc dùng từ khóa
localkhi định nghĩa biến bên trong hàm. Từ khóalocaltạo biến cục bộ, tức là biến chỉ nhìn thấy được bên trong hàm đó. Điều này hạn chế khả năng xung đột biến.
- Mọi sysadmin đều phải làm đôi khi: gỡ lỗi trên console, thật trong trung tâm dữ liệu hoặc ảo qua nền tảng ảo hóa. Nếu bạn phải gỡ lỗi script theo cách đó, bạn sẽ cảm ơn bản thân vì nhớ điều này: Đừng làm dòng trong script quá dài!
Trên nhiều hệ thống, độ rộng mặc định của console vẫn là 80 ký tự. Nếu bạn phải gỡ lỗi script trên console và script có dòng rất dài, bạn sẽ thành "gấu trúc buồn". Ngoài ra, script với dòng ngắn hơn—mặc định vẫn 80 ký tự—dễ đọc và hiểu hơn trong trình soạn thảo thông thường!
Tôi thực sự yêu thích Bash. Tôi có thể dành hàng giờ viết về nó hoặc trao đổi mẹo hay với những người đồng đạo. Hãy chắc chắn để lại những mẹo yêu thích của bạn trong phần bình luận!