Lập trình shell

Giới thiệu UNIX, Linux và shell

Nguyễn Hải Châu (nhchau@gmail.com)
Trường Đại học Công nghệ, ĐHQGHN

Hệ điều hành UNIX

  • UNIX là một hệ điều hành đa nhiệm, đa người dùng được phát triển từ những năm 1970, hiện là một trong các hệ điều hành phổ biến nhất trong thị trường máy chủ
    • Được phát triển tại Bell Labs của hãng AT&T
    • Các tác giả chính của UNIX: Ken Thompson, Dennis Ritchie, Brian Kernighan, Douglas McIlRoy và Joe Ossanna
  • Các hệ điều hành UNIX-like: Linux, BSD UNIX, HP-UX, AIX, Sun OS, Sun Solaris, Mac OS...

Kiến trúc hệ điều hành UNIX

  • shell có thể hiểu là lớp "vỏ", chịu trách nhiệm liên kết người sử dụng, các ứng dụng với kernel (nhân) của hệ điều hành
  • shell có thể sử dụng CLI (command-line interface) hoặc GUI (graphical user
  • Trên UNIX: sh là shell thế hệ đầu tiên, sử dụng CLI
  • Linux: bash, tcsh, ksh, zsh là các shell phổ biến, sử dụng CLI

Xuất xứ tên UNIX

  • Dự án nghiên cứu MULTICS (Multiplexed Information and Computing Service): Dự án xây dựng hệ điều hành time-sharing từ 1965 đến 2000 (http://multicians.org)
  • Hầu hết các hệ điều hành hiện nay chịu ảnh hưởng của MULTICS (thông qua UNIX) một cách trực tiếp (Linux, MacOS) hoặc gián tiếp (Windows)
  • MULTICS chủ yếu sử dụng trong nghiên cứu
  • Sau khi rời khỏi dự án MULTICS, Ken Thompson, Dennis Ritchie, M. D. McIlroy, và J. F. Ossanna quyết định khởi xướng dự án mới, tương tự MULTICS, nhưng có qui mô nhỏ hơn (khoảng 1965).
  • Tên ban đầu của dự án mới là Unics (Uniplexed Information and Computing Service), sau đó chuyển thành UNIX
  • Năm 1972 UNIX được viết lại hoàn toàn bằng ngôn ngữ C

Dennis Richie (9/9/1941 – 12/10/2011)

  • PhD, Harvard University, 1968
  • Sản phẩm: ALTRAN, B, BCPL, C, MULTICS, UNIX
  • Giải thưởng: Turing Award (1983), National Medal of Technology (1998)...

Ken Thompson (4/2/1943)

  • M.S. University of California, Berkeley, 1966
  • Sản phẩm: UNIX, B, Belle, UTF-8, Golang
  • Giải thưởng: Turing Award (1983), National Medal of Technology (1998)...

Douglas McIlroy (1932)

  • PhD, Applied Mathematics, MIT, 1959
  • Sản phẩm: Unix pipeline, phần mềm hướng thành phần, spell, diff, join, graph, speak, tr

Brian Kernighan (1/1/1942)

  • Sản phẩm: UNIX, awk, AMPL, sách lập trình C
  • Chuyên ngành: Khoa học máy tính

Joe Ossanna (10/10/1928 - 28/11/1977)

  • Nghề nghiệp: Kỹ sư điện tử, lập trình viên
  • Sản phẩm: UNIX, nroff

Quá trình tiến hóa của UNIX

Hệ điều hành Linux

  • Là một hệ điều hành UNIX-like, nguồn mở:
    • Phiên bản kernel đầu tiên ra đời 17/9/1991
    • Tác giả: Linus Torvarlds người Phần Lan
  • Lịch sử:
    • 1983: Richard Stallman phát triển dự án GNU Project (GNU is Not UNIX), nhằm tạo ra hệ thống phần mềm tương thích UNIX, và là "free software"
    • 1987: A. Tanenbaum viết MINIX, một hệ điều hành micro-kernel nhằm phục vụ mục tiêu giảng dạy, nghiên cứu: Công bố toàn bộ mã nguồn nhưng không phải là "free software" (cho đến năm 2000)
    • 1991: Linus Torvarlds phát triển Linux trên MINIX nhằm khắc phục vấn đề licensing
    • Ban đầu Linux dùng nhiều ứng dụng sẵn có trên MINIX, sau đó chuyển sang sử dụng các phần mềm GNU, trong đó có các phần mềm soạn thảo text (emacs), công cụ phát triển GNU toolchain: gcc, autoconf, automake, libtool...

Phát triển hiện tại của GNU/Linux

  • Linus Torvarlds: định hướng phát triển kernel
  • Richard Stallman: hỗ trợ phát triển các thành phần thuộc GNU
  • Cộng đồng lập trình viên, công ty... tham gia phát triển các ứng dụng 3rd party
  • Ứng dụng của GNU/Linux: supercomputer, server, desktop, thiết bị cầm tay/thông minh, thiết bị nhúng, thiết bị games và một số thiết bị đặc dụng (home theater, digital security, system rescue...)

Linus Bennedict Torvalds (1969)

  • Quốc tịch: Phần Lan
  • Bằng cấp: M.S., University of Helsinki

Richard Matthew Stallman (16/3/1953)

  • Viết tắt: rms, website: https://www.stallman.org/
  • Quốc tịch: Mỹ
  • Bằng cấp: Harvard University (Bsc), MIT (MSc)
  • Giải thưởng: MacArthur Fellowship, EFF Pioneer Award, ACM Software System Award

Triết lý lập trình UNIX

  • Người khởi xướng triết lý lập trình UNIX: Ken Thompson.
  • Hai nguyên lý chính trong lập trình UNIX:
    • Minimalism
    • Modular

Triết lý lập trình UNIX (theo tài liệu của McIlroy)

  • Mỗi chương trình chỉ làm một nhiệm vụ (và làm tốt nhiệm vụ đó). Nếu có nhiệm vụ mới thì tạo một chương trình mới, không nên bổ sung nhiệm vụ đó cho một chương trình hiện có (do đó làm phức tạp chương trình cũ)
  • Dữ liệu ra (output) của mỗi chương trình có thể sẽ là dữ liệu vào (input) của một số chương trình khác. Do đó:
    • Không nên trộn lẫn dữ liệu ra với các loại thông tin khác
    • Tránh dùng dữ liệu vào ở khuôn dạng nhị phân
    • Ít dùng tương tác khi nhập dữ liệu vào
  • Thiết kế và xây dựng chương trình nhỏ để có thể thử trong vài tuần. Nên xóa bỏ các phần code rắc rối, lỗi để làm lại từ đầu hơn là sửa code lỗi
  • Sử dụng công cụ để giảm nhẹ công việc lập trình

Triết lý lập trình UNIX: tóm tắt

  • Write programs that do one thing and do it well (DOTADIW)
  • Write programs to work together
  • Write programs to handle text streams, because that is a universal interface
  • Áp dụng trong thực tế:

Vai trò của shell trong triết lý lập trình UNIX

  • Các vai trò chính:
    1. UNIX shell có vai trò thông dịch lệnh, đảm nhiệm giao tiếp giữa người sử dụng và hệ điều hành
    2. UNIX shell mặt khác là một ngôn ngữ lập trình, do đó shell và một công cụ phát triển phần mềm
    3. UNIX shell có còn vai trò quan trọng là liên kết các chương trình đã có với nhau để tạo nên một chương trình mới
  • Lập trình UNIX shell:
    1. Viết chương trình theo cú pháp
    2. Biết sử dụng và kết hợp các chương trình sẵn có để tăng hiệu quả lập trình
    3. Kết hợp các chương trình đã có trên UNIX tuân theo các cơ chế định hướng lại vào/ra (I/O redirect) và đường ống (pipe)

Định hướng lại vào/ra

  • Mọi thiết bị ngoại vi, thư mục, file trên UNIX được xem là file
  • Ở chế độ mặc định, một chương trình UNIX (hoặc Linux) có:
    • Dữ liệu vào chuẩn (stdin): Được lấy vào từ bàn phím
    • Dữ liệu ra chuẩn (stdout): Được đưa ra màn hình
    • Dữ liệu báo lỗi chuẩn (stderr): Được đưa ra màn hình
  • stdin, stdout, stderr có thể được thay đổi nhờ vào cơ chế định hướng lại vào/ra:
    • Thay đổi stdin: program < infile.txt
    • Thay đổi stdout: program > outfile.txt
    • Thay đổi stderr: program 2> errfile.txt

Định hướng lại stdin

  • Tìm tên người sử dụng bắt đầu bằng post
grep ^post < /etc/passwd
## postgres:x:26:26:PostgreSQL Server:/var/lib/pgsql:/bin/bash

Định hướng lại stdout

  • Liệt kê tên file trong thư mục hiện hành và ghi vào filelist
ls > filelist
cat filelist | head -9
## a
## a.old
## assign.html
## assign.md
## assign.pdf
## assign.Rmd
## attern=postgres
## awk
## awk.html

Định hướng lại stdout

  • Liệt kê tên file trong thư mục hiện hành và ghi vào filelist
date > filelist
ls >> filelist
cat filelist | head -9
## Sat Nov  5 12:17:56 ICT 2016
## a
## a.old
## assign.html
## assign.md
## assign.pdf
## assign.Rmd
## attern=postgres
## awk

Ví dụ định hướng lại stderr

echo aa > test 2> err
cat test
## aa
cat err

Một số tính năng định hướng lại vào/ra khác

  • Định hướng cả stdoutstderr đến 1 file:
ls > filelist 2>&1 ## Định hướng stderr sang stdout và stdout sang filelist

hoặc đơn giản hơn:

ls >& filelist

Pipe (hoặc pipeline)

  • Pipe chuyển dữ liệu ra của một chương trình A trực tiếp thành dữ liệu vào của chương trình B
  • Ví dụ:
    • ls liệt kê tất cả các file trong một thư mục
    • wc đếm các ký tự, từ hoặc dòng trong một file.
    • Để đếm các file trong một thư mục, sử dụng pipe như sau: ls | wc -l

Đóng stdin, stdout hoặc stderr

ls -l sdfsdf bug1.sh 
ls -l sdfsdf bug1.sh 2> /dev/null
ls -l sdfsdf bug1.sh 2>&-
## ls: cannot access 'sdfsdf': No such file or directory
## -rwxrwxr-x 1 chau chau 134 Oct  6 15:58 bug1.sh
## -rwxrwxr-x 1 chau chau 134 Oct  6 15:58 bug1.sh
## -rwxrwxr-x 1 chau chau 134 Oct  6 15:58 bug1.sh
ls -l sdfsdf bug1.sh  < /dev/null
ls -l sdfsdf bug1.sh  <&-
## ls: cannot access 'sdfsdf': No such file or directory
## -rwxrwxr-x 1 chau chau 134 Oct  6 15:58 bug1.sh
## ls: cannot access 'sdfsdf': No such file or directory
## -rwxrwxr-x 1 chau chau 134 Oct  6 15:58 bug1.sh

Giao tiếp của các chương trình

  • Sử dụng các cơ chế định hướng lại vào/ra, pipe
  • Chuyển đổi dữ liệu bằng text
  • Ngoài các cơ chế nói trên cần có các công cụ hỗ trợ:
    • Phân tích, xử lý text: sed, awk, grep
    • Biểu thức chính qui
    • Tùy biến tham số dòng lệnh: getopts

Nội dung của course

  • Lập trình shell
  • Các cơ chế liên lạc giữa các chương trình/tiến trình của UNIX
    • Định hướng lại vào/ra, pipe
    • Hỗ trợ truyền và phân tích tham số giữa các chương trình: getopts
  • Các công cụ hỗ trợ xử lý text:
    • Mô tả điều kiện tìm kiếm: biểu thức chính qui
    • Tìm kiếm/sửa đổi: grep, sed
    • Xử lý text có cấu trúc cột, tạo báo cáo: awk
  • Một số công cụ hỗ trợ:
    • Hệ soạn thảo: nano, vim, emacs, gedit
    • Các lệnh hay dùng: pwd, date, find, cut, sort, uniq, df, du, tee, kill, killall, ps, md5sum, cmp, diff

Thực hành định hướng lại vào/ra và pipe

  • 1.1. Sử dụng cơ chế pipe và định hướng lại vào/ra để stdin một chương trình B có thể nhận được dữ liệu từ stderr của chương trình A
  • 1.2. Sử dụng cơ chế pipe và định hướng lại vào/ra để stdin của một chương trình B có thể đồng thời nhận được dữ liệu từ stdoutstderr của chương trình A
  • 1.3. Hãy liệt kê danh sách không trùng lặp các chương trình thông dịch lệnh của toàn bộ người sử dụng trong hệ thống, đồng thời in ra tổng số các chương trình thông dịch lệnh khác nhau đó. Chú ý:
    • Danh sách người sử dụng nằm trong /etc/passwd, là file có cấu trúc. Mỗi dòng của có các trường được phân cách bởi dấu :
    • Sử dụng các tiện ích sẵn có của Linux: cut, sort, tee, uniq

Thực hành

  • 1.4. Hãy viết một chương trình nhận tham số vào là một thư mục, kết quả ra thông báo thư mục đó có thay đổi về nội dung các tệp bên trong đó hay không.
    • Cách 1: Sử dụng định hướng lại vào/ra và ứng dụng md5sum
    • Cách 2: Sử dụng định hướng lại vào/ra và ứng dụng diff
  • 1.5. Hãy kiểm tra một chương trình với tên cho trước sinh ra bao nhiêu tiến trình đang tồn tại trong hệ thống

Tài liệu tham khảo

  • Maurice J. Bach, The design of UNIX operating system, Prentice Hall, 1986 (có thể tải từ https://goo.gl/fTMkra)

  • Brian Kernighan, Dennis Ritchie, The C programming language, 2nd edition, Prentice Hall, 1988. (https://goo.gl/oJeCUW)