Skip to content

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]:

  1. Thiết bị hoặc nguồn: /dev/mmcblk0p3, UUID=..., LABEL=..., hoặc tên tượng trưng như proc, tmpfs.
  2. Điểm mount.
  3. Loại filesystem.
  4. Danh sách mount option, cách nhau bằng dấu phẩy.
  5. Cờ cho công cụ dump, thường là 0.
  6. Thứ tự chạy fsck lúc boot: 1 cho rootfs, 2 cho filesystem khác, 0 để bỏ qua.
/etc/fstab
# <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

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