Command line và filesystem¶
Trang này ghi chú các thao tác command line cơ bản và cách làm việc với filesystem trên board Linux nhúng, kèm so sánh với máy host ở những chỗ khác nhau. Nội dung đi theo thứ tự: shell và BusyBox, tra cứu lệnh, cây thư mục, nhóm lệnh thường dùng, process và tài nguyên hệ thống, mount và /etc/fstab, pseudo filesystem, dung lượng và thiết bị lưu trữ, cuối cùng là device file.
Cú pháp shell script (biến, điều kiện, vòng lặp, redirect, pipe) nằm ở trang Shell Script (tab Programming). Chọn loại filesystem cho rootfs và dựng rootfs chỉ đọc nằm ở trang Root filesystem cho thiết bị.
Shell và BusyBox¶
Máy host chạy distro desktop thường dùng bash và bộ lệnh GNU coreutils. Board có rootfs nhỏ, build bằng Buildroot hoặc Yocto, thường dùng BusyBox: một file thực thi duy nhất chứa bản thu gọn của nhiều công cụ Unix như sh, ls, cp, mount, vi [1]. Mỗi công cụ bên trong gọi là một applet. Các lệnh trong /bin, /sbin thường là symlink trỏ về /bin/busybox, và BusyBox chọn applet theo tên được dùng để gọi nó.
ls -l /bin/ls # /bin/ls -> busybox
busybox --list # liệt kê các applet có trong bản build
busybox ls --help # tùy chọn của một applet
Tập applet và tùy chọn của mỗi applet được chọn lúc build BusyBox, nên hai board dùng BusyBox có thể có bộ lệnh khác nhau. Các khác biệt thường gặp so với máy host:
| Máy host (bash, GNU coreutils) | Board (BusyBox) | |
|---|---|---|
| Shell | bash | ash, shell theo chuẩn POSIX; một phần cú pháp mở rộng của bash được bật qua tùy chọn build ASH_BASH_COMPAT [2] |
| Tùy chọn của lệnh | Đầy đủ | Tập con, phụ thuộc cấu hình lúc build |
| Man page | Có | Thường không có; dùng --help hoặc tra man page trên host |
Script viết và chạy thử trên host có thể lỗi trên board vì dùng cú pháp riêng của bash hoặc tùy chọn mà applet không hỗ trợ. Script dành cho board nên dùng #!/bin/sh, chỉ dùng cú pháp POSIX và được chạy thử trên chính board đó.
Tra cứu lệnh¶
| Lệnh | Mục đích |
|---|---|
type cmd, command -v cmd |
Cho biết cmd là builtin của shell, alias hay file thực thi nào |
cmd --help |
Tóm tắt tùy chọn, có ở cả GNU coreutils và BusyBox |
man cmd, man 5 fstab |
Đọc man page; số đứng trước tên là section |
Man page chia thành các section đánh số. Ba section dùng nhiều nhất là 1 (lệnh của người dùng), 5 (định dạng file cấu hình, ví dụ fstab(5)) và 8 (lệnh quản trị hệ thống, ví dụ mount(8)) [3]. Khi tên trùng nhau giữa các section, ví dụ passwd(1) là lệnh đổi mật khẩu còn passwd(5) là định dạng file /etc/passwd, cần ghi rõ số section.
Cây thư mục¶
Linux sắp xếp file theo Filesystem Hierarchy Standard (FHS); man page hier(7) mô tả cách bố trí này trên Linux [4][5]. Bảng sau liệt kê các thư mục chính và điểm cần lưu ý trên thiết bị nhúng:
| Thư mục | Nội dung | Lưu ý trên thiết bị nhúng |
|---|---|---|
/bin, /sbin |
Lệnh cơ bản; /sbin chứa lệnh quản trị |
Với merged /usr, đây là symlink tới /usr/bin, /usr/sbin |
/lib |
Thư viện chia sẻ, module kernel trong /lib/modules/<version> |
|
/usr |
Phần lớn chương trình, thư viện và dữ liệu dùng chung | |
/etc |
File cấu hình hệ thống | Trên rootfs chỉ đọc, /etc thường được phủ bằng overlayfs |
/dev |
Device file | Thường là devtmpfs, do kernel tạo node |
/proc, /sys |
Pseudo filesystem của kernel | Xem mục Pseudo filesystem |
/tmp, /run |
File tạm, dữ liệu runtime (PID file, socket) | Thường là tmpfs, nằm trong RAM, mất khi reboot |
/var |
Dữ liệu thay đổi trong lúc chạy: log, spool, cache | Yocto mặc định đặt /var/log và /var/tmp là symlink vào /var/volatile, một tmpfs [6][7] |
/home, /root |
Thư mục home của user thường và của root | |
/mnt, /media |
Điểm mount tạm thời, thiết bị tháo rời | |
/opt |
Phần mềm cài thêm ngoài distro |
Merged /usr là cách bố trí trong đó /bin, /sbin và /lib chỉ là symlink tới thư mục tương ứng trong /usr. Buildroot bật bằng tùy chọn BR2_ROOTFS_MERGED_USR [8]. Yocto bật bằng distro feature usrmerge, và cấu hình dùng systemd làm init tự thêm feature này [9].
Vì /var/log của image Yocto mặc định nằm trên tmpfs, log mất sau mỗi lần reboot. Muốn giữ log qua reboot thì cần đưa log ra một phân vùng ghi được, cân nhắc số lần ghi lên flash.
Nhóm lệnh thường dùng¶
| Nhóm | Lệnh | Ghi chú |
|---|---|---|
| Thư mục và file | pwd, ls -la, cd, mkdir -p, cp -a, mv, rm -r, ln -s |
cp -a giữ nguyên quyền, owner và symlink |
| Xem nội dung | cat, less, head -n 20, tail -f, hexdump -C |
tail -f theo dõi file log đang được ghi |
| Tìm kiếm | find / -name '*.conf', grep -rn pattern dir |
|
| Nén và đóng gói | tar czf out.tar.gz dir, tar xzf in.tar.gz -C dir, gzip |
|
| Chép file giữa host và board | scp, rsync |
Xem trang SSH |
| Thông tin hệ thống | uname -a, cat /etc/os-release, uptime, date, hostname |
|
| Log | dmesg, logread, journalctl |
logread đọc log của BusyBox syslogd khi ghi vào bộ đệm trong RAM; journalctl dùng với systemd, xem trang Init system |
Process và tài nguyên hệ thống¶
Mỗi chương trình đang chạy là một process, có một số định danh gọi là PID. Các lệnh sau dùng để xem và điều khiển process:
| Lệnh | Mục đích |
|---|---|
ps, top |
Liệt kê process, theo dõi CPU và bộ nhớ theo thời gian |
pidof name, pgrep name |
Tìm PID theo tên chương trình |
kill PID, kill -9 PID, killall name |
Gửi signal; mặc định là SIGTERM, -9 là SIGKILL không thể bắt hoặc bỏ qua |
free, cat /proc/meminfo |
Bộ nhớ đã dùng và còn trống |
cat /proc/cpuinfo, nproc |
Thông tin CPU, số core |
cmd &, jobs, fg, nohup cmd & |
Chạy nền, quản lý job của shell, chạy tiếp sau khi đăng xuất |
ps của BusyBox khác ps của gói procps trên host. Khi bật tùy chọn build DESKTOP, BusyBox ps chỉ nhận -o để chọn cột và -T để hiện thread; khi tắt, nó gần như không nhận tùy chọn nào [10]. Trong cả hai trường hợp, ps không đối số đã liệt kê mọi process, nên không cần ps aux như trên host.
Thông tin chi tiết của từng process nằm trong /proc/<PID>/: cmdline là dòng lệnh, status là trạng thái và bộ nhớ, fd/ là các file đang mở. strace và gdbserver để debug process được trình bày ở trang Debug ứng dụng user space trên board.
Mount và /etc/fstab¶
Linux có một cây thư mục duy nhất bắt đầu từ /. Mỗi filesystem, ví dụ một phân vùng eMMC, thẻ SD, ổ USB hoặc một tmpfs trong RAM, được gắn (mount) vào một thư mục của cây, gọi là điểm mount (mount point). Sau khi mount, nội dung của filesystem hiện ra dưới thư mục đó; nội dung cũ của thư mục bị che đi cho tới khi gỡ mount.
mount # liệt kê filesystem đang mount; hoặc cat /proc/mounts
mount -t ext4 /dev/mmcblk0p3 /mnt/data # mount một phân vùng ext4
mount -o remount,rw / # chuyển rootfs đang mount chỉ đọc sang ghi được
umount /mnt/data # gỡ mount
mount -o loop rootfs.ext4 /mnt # trên host: mount file image để xem nội dung
mount --bind /data/config /etc/app # bind mount: hiện một thư mục ở vị trí khác
findmnt # cây mount, lệnh của util-linux
findmnt và lsblk thuộc gói util-linux. Image chỉ có BusyBox có thể không có hai lệnh này; khi đó dùng cat /proc/mounts và cat /proc/partitions.
Mount option¶
| Option | Ý nghĩa |
|---|---|
ro, rw |
Chỉ đọc, ghi được |
defaults |
Bộ option mặc định: rw, suid, dev, exec, auto, nouser, async [11] |
noatime |
Không cập nhật thời điểm truy cập file mỗi lần đọc, giảm số lần ghi lên flash |
nodev, nosuid, noexec |
Không cho dùng device file, không áp dụng bit setuid/setgid, không cho chạy file thực thi trên filesystem này |
sync |
Ghi đồng bộ, không giữ dữ liệu trong cache |
noauto |
Không mount khi chạy mount -a |
Filesystem FAT (vfat) không lưu owner và quyền của file. Owner và quyền hiển thị được lấy từ các option uid=, gid=, umask=, fmask=, dmask= lúc mount [11].
File /etc/fstab¶
/etc/fstab khai báo các filesystem được mount lúc boot. Mỗi dòng có sáu trường cách nhau bằng khoảng trắng [12]:
- Thiết bị hoặc nguồn:
/dev/mmcblk0p3,UUID=...,LABEL=..., hoặc tên tượng trưng nhưproc,tmpfs. - Điểm mount.
- Loại filesystem.
- Danh sách mount option, cách nhau bằng dấu phẩy.
- Cờ cho công cụ
dump, thường là0. - Thứ tự chạy
fscklúc boot:1cho rootfs,2cho filesystem khác,0để bỏ qua.
# <thiết bị> <điểm mount> <loại> <option> <dump> <fsck>
proc /proc proc defaults 0 0
sysfs /sys sysfs defaults 0 0
devpts /dev/pts devpts defaults,gid=5,mode=620 0 0
tmpfs /tmp tmpfs mode=1777,size=16m 0 0
/dev/mmcblk0p3 /data ext4 defaults,noatime 0 2
Tên thiết bị như /dev/sda1 có thể đổi khi thứ tự phát hiện thiết bị thay đổi. Dùng UUID= hoặc LABEL= thì ổn định hơn; blkid in UUID và label của từng phân vùng.
Người đọc /etc/fstab phụ thuộc init system. Với BusyBox init trong Buildroot, /etc/inittab mặc định chạy mount -a ở giai đoạn sysinit và umount -a -r lúc shutdown [13]. Với systemd, systemd-fstab-generator đọc /etc/fstab lúc boot và tạo mount unit cho từng dòng [14].
Ghi dữ liệu trước khi ngắt nguồn¶
Kernel giữ dữ liệu ghi trong page cache rồi mới ghi xuống thiết bị lưu trữ sau. Nếu board mất nguồn trước lúc đó, dữ liệu vừa ghi có thể mất hoặc filesystem có thể hỏng. sync ép ghi toàn bộ dữ liệu đang chờ xuống thiết bị, và umount cũng ghi hết dữ liệu trước khi gỡ. Trên host, cần chạy sync hoặc umount trước khi rút thẻ SD vừa ghi image. Cơ chế page cache phía kernel nằm ở trang VFS & Page Cache.
Pseudo filesystem¶
Pseudo filesystem là filesystem không nằm trên thiết bị lưu trữ: nội dung do kernel tạo ra khi đọc, hoặc nằm trong RAM. Các pseudo filesystem thường gặp:
| Filesystem | Điểm mount | Nội dung | Ví dụ dùng |
|---|---|---|---|
| procfs | /proc |
Thông tin process và kernel | /proc/cpuinfo, /proc/meminfo, /proc/cmdline, /proc/mounts |
| sysfs | /sys |
Thiết bị, driver và bus mà kernel quản lý | /sys/class/net/, /sys/class/thermal/ |
| devtmpfs | /dev |
Device node do kernel tạo | /dev/ttyS0, /dev/mmcblk0 |
| tmpfs | /tmp, /run |
Filesystem trong RAM | File tạm, PID file |
| debugfs | /sys/kernel/debug |
Thông tin debug của driver | mount -t debugfs none /sys/kernel/debug |
/proc/sys/ chứa tham số của kernel có thể chỉnh lúc chạy. Lệnh sysctl đọc và ghi các tham số này, ví dụ sysctl -w net.ipv4.ip_forward=1 tương đương ghi 1 vào /proc/sys/net/ipv4/ip_forward. Kernel tạo và phục vụ các pseudo filesystem này như thế nào được trình bày ở trang Pseudo Filesystem (tab Linux Kernel).
Dung lượng và thiết bị lưu trữ¶
| Lệnh | Mục đích |
|---|---|
df -h |
Dung lượng đã dùng và còn trống của từng filesystem đang mount |
df -i |
Số inode đã dùng; filesystem có thể hết inode trước khi hết dung lượng khi chứa rất nhiều file nhỏ |
du -sh dir/* |
Dung lượng của từng thư mục con |
cat /proc/partitions, lsblk |
Danh sách block device và phân vùng |
blkid |
Loại filesystem, UUID và label của từng phân vùng |
cat /proc/mtd |
Danh sách phân vùng MTD trên flash NOR hoặc NAND thô |
Tên block device trên board thường gặp: /dev/mmcblkN cho eMMC hoặc thẻ SD, với phân vùng /dev/mmcblkNpM; /dev/sdX cho ổ USB hoặc SATA. Flash NOR và NAND thô không phải block device thông thường mà đi qua MTD subsystem, và trên NAND thường dùng UBI kèm UBIFS; phần này trình bày ở trang Flash Storage (MTD, MMC).
tmpfs dùng RAM, nên dữ liệu ghi vào /tmp, /run hoặc /var/volatile chiếm bộ nhớ của hệ thống. Option size= khi mount tmpfs giới hạn dung lượng tối đa.
Device file¶
Device file trong /dev là điểm truy cập từ user space tới driver. ls -l cho biết loại và số hiệu của device file, ví dụ trên một máy host Ubuntu:
$ ls -l /dev/ttyS0 /dev/mmcblk0
crw-rw---- 1 root dialout 4, 64 Nov 10 08:00 /dev/ttyS0
brw-rw---- 1 root disk 179, 0 Nov 10 08:00 /dev/mmcblk0
Ký tự đầu tiên là c với character device hoặc b với block device. Hai số 4, 64 là major number và minor number: major chỉ driver phụ trách, minor chỉ thiết bị cụ thể trong driver đó.
Device node được tạo theo một trong các cách: bảng thiết bị tĩnh lúc build image, devtmpfs (kernel tự tạo node), devtmpfs kèm mdev của BusyBox, hoặc devtmpfs kèm udev. Buildroot cho chọn giữa bốn cách này trong menu "/dev management" [8]. mdev và udev còn đặt owner, group và quyền cho node; phần quyền truy cập device file nằm ở trang User, quyền và package. Cơ chế device file phía kernel nằm ở trang Device File & ioctl.
Liên quan¶
- Shell Script (Programming): cú pháp shell script, redirect và pipe.
- Pseudo Filesystem (Linux Kernel): procfs, sysfs, debugfs, configfs ở phía kernel.
- Device File & ioctl (Linux Kernel): driver tạo và phục vụ device file.
- VFS & Page Cache (Linux Kernel): tầng filesystem chung và page cache.
- Flash Storage (MTD, MMC) (Linux Kernel): MTD, UBI và UBIFS.
- Root filesystem cho thiết bị: chọn filesystem cho rootfs, rootfs chỉ đọc và overlayfs.
- Init system: nơi chạy
mount -avới BusyBox init, mount unit của systemd. - User, quyền và package: user, quyền trên file và device file, package manager.
Tài liệu tham khảo¶
[1] - BusyBox - giới thiệu dự án BusyBox
[2] - busybox/shell/ash.c - tùy chọn build ASH_BASH_COMPAT
[3] - man-pages(7) - các section của man page
[4] - Filesystem Hierarchy Standard 3.0 - Linux Foundation
[5] - hier(7) - mô tả cây thư mục
[6] - OpenEmbedded-Core: base-files - recipe tạo symlink /var/log, /var/tmp vào /var/volatile và file fstab mount tmpfs tại /var/volatile
[7] - OpenEmbedded-Core: bitbake.conf - giá trị mặc định của FILESYSTEM_PERMS_TABLES
[8] - Buildroot: system/Config.in - tùy chọn BR2_ROOTFS_MERGED_USR và các cách quản lý /dev
[9] - OpenEmbedded-Core: init-manager-systemd.inc - thêm distro feature systemd usrmerge
[10] - busybox/procps/ps.c - tùy chọn của applet ps
[11] - mount(8) - util-linux: option defaults, --bind, option của FAT
[12] - fstab(5) - util-linux: định dạng /etc/fstab
[13] - Buildroot: package/busybox/inittab - inittab mặc định của Buildroot
[14] - systemd-fstab-generator(8) - tạo mount unit từ /etc/fstab