Học Linux 1: Shell

2018-05-28

Content:

1. Shell

Shell là một giao diện nguời dùng (user interface) dùng để truy cập đến các dịch vụ của hệ điều hành. Nhìn chung, shell sử dụng giao diện dòng lệnh (command-line interface, command-line shell, command language interpreter - CLI) hoặc giao diện nguời dùng đồ hoạ (graphical user interface - GUI). Gọi là shell (vỏ) vì nó là lớp ngoài cùng bao quanh nhân của hệ điều hành.

Ví dụ: bạn muốn tạo một folder mới trên máy tính, bất kể đang sử dụng Unix-like systems hay Windows, có thể sử dụng 2 cách:

  • GUI: dùng chuột, nhấp chuột phải chọn new folder.
  • CLI: CLI trên Windows là Command Prompt, trên Unix-like systems thì đa dạng hơn, và lệnh tạo folder mới đa số là mkdir path_to_folder.

Một số ứng dụng có thể implement một phiên bản CLI cho riêng nó bên cạnh GUI. Ví dụ khi cài Sublime Text, bạn vừa có thể mở nó bằng việc click vào icon, hoặc sử dụng CLI và gõ sublime.

Một đặc điểm của CLI đó là nó có thể lưu một chuỗi các lệnh vào file để tái sử dụng, gọi là shell script files.

2. Unix shell

Unix shell là CLI trên các Unix-like systems.

Unix shell đầu tiên là Thompson shell, giới thiệu các chức năng chung cơ bản cho các Unix shell sau này: đuờng ống (piping), các cấu trúc điều khiển (control structures) sử dụng if và goto, và ký tự đại diện (wildcard character).

PWB shell hay Mashey shell là phiên bản đuợc tăng cuờng của Thompson shell, tập trung vào lập trình shell (shell programming). Một số thay đổi đáng lưu ý:

  • Giới thiệu shell variables: $HOME, $PATH, etc. Đây là tiền thân của các biến môi truờng (environment variable), bao gồm cả cơ chế tìm đuờng dẫn (search path mechanism) sử dụng $PATH.
  • Mở rộng control structures: if, then, else, switch, while, break, etc.
  • Etc.

Nhưng 2 Unix shells đời đầu đuợc phân phối và có ảnh huởng lớn nhất là Bourne shellC shell. Bourne shell giới thiệu các đặc trưng cơ bản còn lại đuợc xem là phổ biến trên tất cả Unix shells: here documents, command substitution, thêm nhiều variables và control structures. Truớc đây, tên của Bourne shell là sh, đuờng dẫn của nó trên hệ thống phân cấp file Unix (Unix file system hierarchy) là /bin/sh. Tuy nhiên vì có nhiều phiên bản shell tuơng thích đuợc phát triển từ sh nên trên nhiều hệ điều hành; sh có thể link đến Bourne shell, hoặc cũng là thể là một symbolic link hoặc hard link đến các Unix shells đó như: ash, bash, ksh, zsh, etc.

Bash (Bourne-Again shell) đuợc phát triển như một phần của GNU Project và cung cấp nhiều chức năng hơn so với Bourne shell. Bash là shell phổ biến nhất trên các hệ điều hành Linux hiện đại và MacOS. Từ giờ trở đi bài viết sẽ giả sử shell đuợc sử dụng là bash shell (hay hay viết gọn là bash).

Cần phân biệt shell và terminal: shell là chuơng trình xử lý lệnh và trả về kết quả, terminal là chuơng trình bao bên ngoài shell và chạy shell. Ví dụ trên Linux và MacOS, khi terminal đuợc mở thì một cửa sổ đuợc hiển thị để khởi tạo môi truờng cho terminal và chuơng trình shell đuợc chạy lên trên cửa sổ đó, cho phép nguời dùng tuơng tác với shell (gõ lệnh và nhận kết quả trả về tuơng ứng). Một số terminal phổ biến như: gnome-terminal, konsole, xterm, eterm, etc. Đây cũng là cách tuơng tác với shell phổ biến (bằng cách chạy một chuơng trình terminal).

Để biết đưọc shell nào đang đưọc sử dụng trên hệ thống, tham khảo link.

3. Phân loại shell

Bài viết này phân shell làm các loại sau:

  • Interactive shell.
  • Non-interactive shell.
  • Login shell
  • Non-login shell

Các loại shell khác nhau sẽ có cách hành xử khác nhau: configuration files nào sẽ đuợc thực thi, khi nào thì có dấu nhắc (prompt), etc. Chúng ta sẽ đề cập đến configuration files sau.

3.1. Login và non-login shell

Nếu khi bạn chạy một chuơng trình shell, bạn cần phải nhập username và password truớc khi sử dụng thì đó là login shell, nguợc lại là non-login shell (ví dụ khi chạy bằng terminal).

Một số ví dụ về login shell:

  • Khi bạn gõ username và password để truy cập vào desktop thì về cơ bản bạn đã khởi động một login shell (login shell này khởi động desktop và các thứ tuơng tự).
  • Sau khi truy cập đuợc vào desktop, một truờng hợp nữa để bạn khởi động một login shell khác là khi desktop có vấn đề và bạn cần chuyển sang một terminal ảo (virual terminal) bằng tổ hợp Ctrl + Alt + F1.

Những script files đuợc thực thi khi khởi tạo một login shell là:

  • /etc/profile
  • ~/.bash_profile
  • ~/.bash_login
  • ~/.profile
  • ~/.bash_logout

Để kiểm tra login shell, có thể sử dụng lệnh sau:

shopt -q login_shell && echo 'Login shell' || echo 'Not login shell'

3.2. Interactive và non-interactive shell

Interactive shell, đúng như tên gọi, là loại shell tuơng tác với user, cho user biết ngay kết quả tuơng ứng với từng lệnh đưọc nhập vào tại dòng có prompt. Nguợc lại, nếu shell đọc một tập các lệnh đưọc lưu trong một shell script thì sẽ không cần phải hiện thị prompt, shell trong truờng hợp ày là non-interactive (không tuơng tác đuợc với user).

Để kiểm chứng, gõ lệnh sau vào Terminal và vào một file sh. Sau khi bấm enter ở Terminal hoặc thực thi file sh, kết quả tuơng ứng nên là InteractiveNot interactive.

[[ $- == *i* ]] && echo 'Interactive' || echo 'Not interactive'

Dễ thấy rằng mỗi khi Terminal đuợc mở lên thì một interactive shell sẽ đuợc khởi động. Để khởi động lại có thể tắt Terminal và mở lại, hoặc có thể gõ lệnh đến file thực thi của shell (ví dụ nếu dùng bash thì dùng lệnh bash). Mỗi khi một interactive và non-login shell đuợc khởi tạo, ~/.bashrc/etc/bash.bashrc script file sẽ đuợc thực thi. Non-interactive shell nguợc lại không thực thi 2 files này, cần lưu ý điều này vì nó thuờng ảnh huởng đến biến PATH. Ví dụ bạn sử dụng biến PATH trong một script file nào đó, sau đó chỉnh sửa PATH~/.basrc, nếu chạy script file ngay sau đó thì có thể gây ra lỗi vì ~/.bashrc không đuợc thực thi dẫn đến PATH chưa đưọc cập nhập lại.

##** 4. Configuration files **

Các configuration files của một chuơng trình shell có thể đuợc chia làm 2 loại: systemwide (những file có tác động lên toàn hệ thống) và user session (những file chỉ tác động lên môi truờng của user). 7 configuration files của bash shell đuợc thảo luận trong phần này là:

  • /etc/profile: system wide, file khởi tạo cho hệ thống.
  • ~/.bash_profile: user session, file khởi tạo cho user.
  • ~/.profile: giống ~/.bash_profile, nhưng cũng được sử dụng cho các loại shell khác.
  • ~/.bash_login: user session.
  • ~/.bash_logout: user session, thực thi khi một login shell kết thúc.
  • ~/.bashrc: user session.
  • /etc/bash.bashrc: phiên bản system wide của ~/.bashrc (áp dụng cho toàn hệ thống, đuợc thực thi mỗi khi một interactive shell bắt đầu).

Loại bash shell nào thực thi file nào đã đuợc đề cập ở mục 3. Ở đây mình nói thêm một chút về thứ tự thực thi các files đối với login shell. Khi một login shell khởi động: /etc/profile sẽ đuợc thực thi đầu tiên; kế đến theo thứ tự ~/.bash_profile, ~/.bash_login, ~/.profile, file nào đầu tiên tồn tại và đuợc cấp quyền đọc sẽ đuợc thực thi (các file còn lại thì không), cuối cùng ~/.bash_logout đuợc thực thi khi bash shell kết thúc.

Đề cập thêm rằng Ubuntu sử dụng ~/.profile và thuờng không có ~/.bash_profile. Bạn cũng không nên tạo và nếu có tạo thì nên chú ý rằng ~/.profile lúc này sẽ không còn đuợc thực thi (theo giải thích ở trên).

Vậy nên việc quyết định đặt các thiết lập (variables, settings, etc.) vào file nào tuỳ thuộc vào 2 yếu tố:

  • Bạn muốn thiết lập này áp dụng cho toàn hệ thống hay chỉ cho một user nào đó?
  • Bạn muốn thiết lập này đưọc thực thi mỗi khi bắt đầu một interactive (và non-login) shell hay chỉ khi bắt đầu một login shell?

Ví dụ về alias

Bạn muốn lệnh rm luôn hỏi xác nhận truớc khi xoá file, có thể làm điều này bằng cách tạo alias rm='rm -i'. Bạn muốn chỉ có bạn mới dùng đuợc alias này (user session) và alias sẽ hoạt động mỗi khi bắt đầu một interactive shell, vậy alias này sẽ đuợc đặt ở ~/.bashrc. Sau khi thêm vào file ~/.bashrc, để alias có hiệu lực, một interactive shell cần đuợc khởi động (như đề cập ở mục 3), có thể làm việc này bằng (ít nhất) là 2 cách sau: khởi động lại Terminal hoặc dùng lệnh source ~/.bashrc.

Tuy nhiên, cách đuợc khuyên dùng là đặt tất cả các alias vào một file riêng ~/.bash_aliases, và trong ~/.bashrc chỉ cần “source” đến file này:

if [ -f ~/.bash_aliases ]; then
source ~/.bash_aliases
fi

Ví dụ về thêm đuờng dẫn vào PATH

PATH là biến môi truờng (environment variable) dùng để chỉ định các thư mục chứa các file thực thi. Lấy ví dụ bạn muốn sử dụng các file thực thi của riêng bạn tại đuờng dẫn path/to/dir giống như sử dụng các câu lệnh cd, rm, etc.; thì đuờng dẫn path/to/dir cần đuợc thêm vào PATH.

Giả sử bạn đang chạy Terminal, khi dùng lệnh printenv, các environment variables sẽ đuợc hiển thị, trong đó có PATH. Một cách để thêm đuờng dẫn vào PATH là:

export PATH="$PATH:/path/to/dir"

Tuy nhiên giá trị mới của PATH lúc này chỉ có hiệu lực trong cửa sổ Terminal hiện tại (hay nói cách khác PATH lúc này là một environment variable của Terminal process hiện tại). Để PATH có hiệu lực vĩnh viễn, làm tuơng tự như ví dụ thứ nhất về alias.

References

1. Shell (computing), Wikipedia

2. Unix shell, Wikipedia

3. Different shell types: interactive, non-interactive, login

4. Unix Power Tools, 3rd edition, O’reilly

5. Starting a “login shell” or “interactive shell” using switch user (su) command in CentOS/RHEL 7

6. What are login and non-login shells?

7. How to permanently set $PATH on Linux/Unix?

8. How do I create a permanent Bash alias?