高级shell编程笔记(第十三章 系统与管理命令)

第十三章 系统与管理命令

在/etc/rc.d 目录中的启动和关机脚本中包含了好多有用的(和没用的)这些系统管理命令。这些命令通常总是被 root 用户使用,用与系统维护或者是紧急文件系统修复。一定要小心使用这些工具,因为如果滥用的话,它们会损坏你的系统。

Users 和 Groups 类命令

users

显示所有的登录的用户。这个命令与 who -q 基本一致。

groups

列出当前用户和他所属于的组。这相当于$GROUPS内部变量,但是这个命令将会给出组名字,还不是数字。

[root@localhost ~]# groups 
root
[root@localhost ~]# echo $GROUPS
0

chown,chgrp

chown 命令将会修改一个或多个文件的所有权。对于 root 来说这是一种非常好的将文件的所有权从一个用户换到另一个用户的方法。一个普通用户不能修改文件的所有权, 即使他是文件的宿主也不行。

chgrp 将会修改一个或多个文件党组所有权。你必须是这些文件的宿主,并且是目的组的成员(或者 root),这样才能使用这个操作。

useradd,userdel

useradd 管理命令将会在系统上添加一个用户帐号,并且如果指定的话,还会为特定的用户创建 home 目录。相应的 userdel 命令将会从系统上删除一个用户帐号,并且删除相应的文件。

注意: adduser 命令与 useradd 是相同的,adduser 通常都是一个符号链接。

usermod

修改用户帐号。可以修改密码、组身份、截止日期或者给定用户帐号的其他的属性。使用这个命令,用户的密码可能会被锁定,因为密码会影响到帐号的有效性。

groupmod

修改指定组。组名字或者 ID 号都可以使用这个命令来修改。

id

id 将会列出当前进程的真实和有效用户 ID,还有用户的组 ID。这与 Bash 的内部变量 $UID、 $EUID 和 $GROUPS 很相像。

who

显示系统上所有已经登录的用户。

-m 选项将会只给出当前用户的详细信息。将任意两个参数传递到 who 中都等价于 who -m,就像 whoami 或者 who The Man。

[root@localhost ~]# who
root     tty1         2020-07-20 14:27
root     pts/1        2020-08-23 08:23 (192.168.1.113)
[root@localhost ~]# who -m
root     pts/1        2020-08-23 08:23 (192.168.1.113)
[root@localhost ~]# whoami 
root
[root@localhost ~]# who The Man
root     pts/1        2020-08-23 08:23 (192.168.1.113)

w

显示所有的登录的用户和属于它们的进程。这是一个 who 的扩展版本。w 的输出可以通过管道传递到 grep 中, 这样就可以查找指定的用户或进程。

logname

显示当前用户的登录名(可以在/var/run/utmp 中找到)。这与上边的 whoami 很相近。

[root@localhost ~]# whoami 
root
[root@localhost ~]# logname 
root
...然而...
[root@localhost ~]# su - bozo
[bozo@localhost ~]$ whoami 
bozo
[bozo@localhost ~]$ logname 
root

注意: logname 只会打印出登录的用户名, 而 whoami 将会给出附着到当前进程的用户名。就像我们上边看到的那样, 这两个名字有时会不同。

su

使用一个代替的用户来运行一个程序或脚本。su rjones 将会以 rjones 来启动一个 shell。一个不加参数的 su 默认就是 root。参见 Example A-15。

sudo

以 root(或其他用户)的身份来运行一个命令。这个命令可以运行在脚本中,这样就允许以正规的用户身份来运行脚本。

passwd

设置、修改或者管理用户的密码。passwd 命令可以用在脚本中,但可能你不想这么用。

Example 13-1 设置一个新密码

#!/bin/bash
#
ROOT_UID=0
E_WRONG_USER=65
E_NOSUCHUSER=70
SUCCESS=0

if [ "$UID" -ne "$ROOT_UID" ];then
  echo; echo "Only root can run this script."; echo
  exit $E_WRONG_USER
else
  echo
  echo "You should know better than to run this script, root."
  echo "Even root users get the blues... "
  echo
fi

username=bozo
NEWPASSWORD=security_violation

grep -q "$username" /etc/passwd
if [ $? -ne $SUCCESS ];then
  echo "User $username does not exist."
  echo "No password changed."
  exit $E_NOSUCHUSER
fi
echo "$NEWPASSWORD" | passwd --stdin "$username"
echo; echo "User $username's password changed!"
exit 0

passwd 命令的 -l, -u, 和 -d 选项允许锁定, 解锁,和删除一个用户的密码。只有 root 用户可以使用这些选项。

ac

显示用户登录的连接时间,就像从 /var/log/wtmp 中读取一样。这是 GNU 的一个统计工具。

[root@localhost ~]# ac
	total     1032.24

last

用户最后登录的信息,就像从/var/log/wtmp 中读出来一样。这个命令也可以用来显示远端登录。比如,显示最后几次系统的重启信息:

[root@localhost ~]# last reboot
reboot   system boot  2.6.32-431.el6.x Mon Jul 20 14:27 - 08:40 (33+18:13)  
......   
reboot   system boot  2.6.32-431.el6.x Tue Mar 31 16:49 - 18:00 (10+01:10)  
reboot   system boot  2.6.32-431.el6.x Tue Mar 31 14:47 - 15:09  (00:21)    

wtmp begins Tue Mar 31 14:47:43 2020

newgrp

不用登出就可以修改用户的组 ID。并且允许存取新组的文件。因为用户可能同时属于多个组,这个命令很少被使用。

终端类命令

tty

显示当前用户终端的名字。注意每一个单独的 xterm 窗口都被算作一个不同的终端。

[root@localhost ~]# tty
/dev/pts/1

stty

显示并(或)修改终端设置。这个复杂命令可以用在脚本中,并可以用来控制终端的行为和其显示输出的方法。参见这个命令的 info 页, 并仔细学习它。

Example 13-2 设置一个擦除字符

#!/bin/bash
#
echo -n "What is your name? "
read name   #试试退格键来删除输入的字符。有什么问题?

echo "Your name is $name."

stty erase '#'   # 将 "hashmark" (#) 设置为退格字符.
echo -n "What is your name? "
read name
echo "Your name is $name."
#警告: 即使在脚本退出后, 新的键值还是保持设置.
exit 0

Example 13-3 关掉终端对于密码的echo

#!/bin/bash
#
echo
echo -n "Enter password"
read passwd
echo "password is $passwd"
echo -n "if someone had been looking over your shoulder,"
echo "your password would have been compromised."

echo&&echo

stty -echo   # 关闭屏幕的 echo.
echo -n "Enter password again "
read passwd
echo
echo "password is $passwd"
echo

stty echo   # 恢复屏幕的 echo.
exit 0

一个具有创造性的stty命令用法,检测用户所按的键(不用敲回车)
Example 13-4 按键检测

#!/bin/bash
#
echo
old_tty_setting=$(stty -g)   # 保存老的设置(为什么?).
stty -icanon   #设置一次性读完操作,不需要按enter
Keypress=$(head -c1)

echo
echo "Key pressed was \""$Keypress"\"."
echo
stty "$old_tty_setting"   # 恢复老的设置.
exit 0

参见Example 9-3

注意: 终端与模式 terminals and modes 一般情况下,一个终端都是工作在canonical(标准)模式下。当用户按键后,事实上所产生的字符并没有马上传递到运行在当前终端上的程序。终端上的一个本地的缓存保存了这些按键,当用按下 ENTER 键的时候,才会将所有保存的按键信息传递到运行的程序中。这就意味着在终端内部存在一个基本的行编辑器。

在使用 canonical 模式的时候,可以对本地终端行编辑器所定义的特殊按键进行重新定义。

[root@localhost shell]# cat filename.txt 
hello word

[root@localhost shell]# wc -c < filename.txt 
12

控制终端的进程只保存了 12 个字符(11 个字母加上一个换行, 虽然用户敲了 26 个按键。

在 non-canonical (“raw”) 模式,每次按键(包括特殊定义的按键,比如 ctl-H)将会立即发送一个字符到控制进程。

Bash 提示符禁用了 icanon 和 echo,因为它用自己的更好的行编辑器代替了终端的基本行编辑器。比如,当你在 Bash 提示符下敲 ctl-A 的时候,终端将不会显示 ^A,但是 Bash 将会获得\1 字符,然后解释这个字符,这样光标就移动到行首了。

setterm

设置特定的终端属性。这个命令将向它的终端的 stdout 写一个字符串,这个字符串将修改终端的行为。

setterm 命令可以被用在脚本中来修改写到 stdout 的文本的外观,虽然如果你仅仅只想完成这个目的,还有特定的更好的工具可以用。

[root@localhost shell]# setterm -cursor off   #隐藏光标
[root@localhost shell]# setterm -cursor on

[root@localhost shell]# setterm -bold on   #终端黑体显示
[root@localhost shell]# setterm -bold off

test

显示或初始化终端设置。可以说这是 stty 的功能比较弱的版本。

setserial

设置或者显示串口参数。这个脚本只能被 root 用户来运行,并且通常都在系统安装脚本中使用。

getty,agetty

一个终端的初始化过程通常都是使用 getty 或 agetty 来建立,这样才能让用户登录。这些命令并不用在用户的 shell 脚本中。它们的行为与 stty 很相似。

mesg

使用或禁用当前用户终端的存取权限。禁用存取权限将会阻止网络上的另一用户向这个终端写消息。

注意: 当你正在编写文本文件的时候,在文本中间突然来了一个莫名其妙的消息,这对你来说是非常烦人的。在多用户的网络环境下,当你不想被打断的时候,你可能因此希 望禁用对你终端的写权限。

wall

这是一个缩写单词 “write all”,也就是向登录到网络上的任何终端的所有用户都发送 一个消息。最早这是一个管理员的工具,很有用。比如,当系统有问题的时候,管理可以警告系统上的所有人暂时离开 (参见 Example 17-1)。

注意: 如果某个特定终端使用 mesg 来禁止了写权限,那么 wall 将不会给它发消息。

信息与统计类

uname

输出系统的说明(OS、内核版本等等)到 stdout。使用 -a 选项将会给出详细的信息 (参见 Example 12-5)。使用-s 选项只会输出 OS 类型。

arch

显示系统的硬件体系结构。等价于 uname -m。参见 Example 10-26。

lastcomm

给出前一个命令的信息,存储在/var/account/pacct 文件中。命令名字与用户名字都可以使用选项来指定。这是 GNU 的一个统计工具。

lastlog

列出系统上所有用户最后登录的时间。存在/var/log/lastlog 文件中。

lsof

列出打开的文件。这个命令将会把所有当前打开的文件列出一份详细的表格,包括文件的所有者信息、尺寸、与它们相关的信息等等。当然,lsof 也可以管道输出到 grep 和(或) awk 来分析它的结果。

strace

为了跟踪系统和信号的诊断和调试工具。调用它最简单的方法就是 strace COMMAND。

nmap

网络端口扫描器。这个命令将会扫描一个服务器来定位打开的端口,并且定位这些端口相关的服务。这是一个防止网络被黑客入侵的一个重要的安全工具。

#!/bin/bash
#
SERVER=$HOST
PORT_NUMBER=25   #SMTP端口

nmap $SERVER | grep -w "$PORT_NUMBER"   
#grep -w 匹配整个单词,这样就不会匹配类似于1025这种含有25的端口了

exit 0

nc

nc(netcat)工具是一个完整的工具包,可以使用它来连接和监听 TCP 和 UDP 端口。它可以用来作为诊断和测试工具,也可以用来作为基于脚本的 HTTP 客户端和服务器的组件。

Example 13-5 Checking a remote server for identd

#!/bin/bash
#
E_BADARGS=65
IDPORT=113
RAND1=999
RAND2=31337

case "${2}" in
  "" ) echo "需要主机和至少一个端口"
       exit $E_BADARGS ;;
esac

nc -z -w 9 "$1" $IDPORT || { echo "Oops, $1 isn't running identd." ; exit 0 ; }
#-z 连接立即关闭,不进行数据交换
#-w 执行超时时间,如果不指定就是tcp超时的时间

RP=`expr $$ % $RAND1 + $RAND2`
TRG="$1"
shift

while test "$1"
do
  nc -v -w 8 -p ${RP} "$TRG" ${1} < /dev/null > /dev/null &
  #-v 输出检测结果,-vv表示更详细的信息
  PROC=$!
  sleep 3
  echo "${1},${RP}" | nc -w 4 -r "$TRG" $IDPORT 2>&1
  sleep 2
  kill -HUP $PROC
  PR=`expr ${RP} + 1`
  shift
done
exit $?  

free

使用表格形式来显示内存和缓存的使用情况。这个命令的输出非常适合于使用 grep, awk 或者 Perl 来分析。procinfo 命令将会显示 free 命令所能显示的所有信息,而且更多。

procinfo

从/proc pseudo-filesystem 中提取和显示所有信息和统计资料。这个命令将给出更详细的信息。

lsdev

显示设备,也就是显示安装的硬件。

du

递归的显示(磁盘)文件的使用状况。除非指定默认是当前工作目录。

df

使用列表的形式显示文件系统的使用状况。

dmesg

将所有的系统启动消息输出到 stdout 上。方便出错并且可以查出安装了哪些设备驱动和察看使用了哪些系统中断。dmesg 命令的输出当然也可以在脚本中使用 grep, sed, 或 awk 来进行分析。

stat

显示一个或多个给定文件(也可以是目录文件或设备文件)的详细的统计信息。
如果目标文件不存在,stat 将会返回一个错误信息。

vmstat

显示虚拟内存的统计信息。

netstat

显示当前网络的统计和信息,比如路由表和激活的连接。这个工具存取/proc/net(第 27 章) 中的信息。参见 Example 27-3。
netstat -r 等价于 route 命令。

uptime

显示系统运行的时间,还有其他一些统计信息。

hostname

显示系统的主机名字。这个命令在 /etc/rc.d 安装脚本(/etc/rc.d/rc.sysinit 或类似的)中设置主机名。等价于 uname -n,并且与$HOSTNAME 内部变量很相像。

与 hostname 命令很相像的命令还有 domainname、dnsdomainname、nisdomainname和 ypdomainname 命令。使用这些来显示或设置系统 DNS 或者 NIS/YP 域名。对于 hostname 命令来说使用不同的选项一样可以达到上边这些命令的目的。

hostid

显示主机的 32 位的 16 进制 ID。

注意: 这个命令据说对于特定系统可以获得一个"唯一"的序号。某些产品的注册过程可能会需要这个序号来作为用户的许可证。不幸的是 hostid 只会使用字节转换的方法来用 16 进制显示机器的网络地址。

sar

sar (System Activity Reporter 系统活动报告) 命令将会给出系统统计的一个非常详细的概要。Santa Cruz Operation(“老” SCO)公司在 1999 年 4 月份以开源软件的形式发布了 sar。这个命令并不是基本 Linux 发行版的一部分,但是你可以从 Sebastien Godard 写的 sysstat utilities 包中获得这个工具。

[root@localhost shell]# sar 
Linux 2.6.32-431.el6.x86_64 (localhost) 	08/24/2020 	_x86_64_	(2 CPU)

12:00:01 AM     CPU     %user     %nice   %system   %iowait    %steal     %idle
12:10:01 AM     all      0.07      0.00      0.02      0.07      0.00     99.84
......
07:30:01 AM     all      0.07      0.00      0.01      0.05      0.00     99.87
07:40:01 AM     all      0.06      0.00      0.02      0.05      0.00     99.87

Average:        CPU     %user     %nice   %system   %iowait    %steal     %idle
Average:        all      0.06      0.00      0.02      0.05      0.00     99.87

readelf

显示指定的 elf 格式的 2 进制文件的统计信息。这个工具是 binutils 工具包的一部分。

[root@localhost shell]# readelf  -h /bin/ls
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x4027e0
  Start of program headers:          64 (bytes into file)
  Start of section headers:          115000 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         8
  Size of section headers:           64 (bytes)
  Number of section headers:         32
  Section header string table index: 31

size

size [/path/to/binary] 命令可以显示 2 进制可执行文件或归档文件每部分的尺寸。这个工具主要是程序员使用。

[root@localhost shell]# size /bin/ls
   text	   data	    bss	    dec	    hex	filename
 100931	   8000	      0	 108931	  1a983	/bin/ls

系统日志类

logger

附加一个用户产生的消息到系统日之中 (/var/log/messages)。不是 root 用户也可以调用 logger。

通过在脚本中调用一个 logger 命令,就可以将调试信息写到/var/log/messages 中。

logger -t $0 -i Logging at line "$LINEVO"
#"-t" 选项可以为长的入口指定标签.
#"-i" 选项记录进程 ID.

logrotate

这个工具用来管理系统的 log 文件,可以在合适的时候轮换、压缩、删除和(或)e-mail 它们。这个工具将从老的 log 文件中取得一些杂乱的记录保存在/var/log 中。通常使用 cron 来每天运行 logrotate。

在/etc/logrotate.conf 中添加合适的入口就可以管理自己的 log 文件了,就像管理系统 log 文件一样。

注意: Stefano Falsetto 创造了 rottlog,他认为这是 logrotate 的改进版本。

作业控制

ps

进程统计: 通过进程所有者和 PID(进程 ID)来列出当前执行的进程。通常都是使用 ax 选项来调用这个命令,并且结果可以通过管道传递到 grep 或 sed 中来搜索特定的进程 (参见 Example 11-12 和 Example 27-2)。

pgrep,pkill

ps 命令与 grep 或 kill 结合使用.

[root@localhost shell]# ps -ef | grep mysql
root      3198     1  0 Jul21 ?        00:00:00 /bin/sh /data/mysql-5.7.31/bin/mysqld_safe
mysql     4286  3198  0 Jul21 ?        00:59:26 /data/mysql-5.7.31/bin/mysqld --basedir=/data/mysql-5.7.31 --datadir=/data/mysql-5.7.31/datadb --plugin-dir=/data/mysql-5.7.31/lib/plugin --user=mysql --log-error=/data/mysql-5.7.31/logs/mysql-error.log --open-files-limit=65535 --pid-file=/data/mysql-5.7.31/temp/mysqld.pid --socket=/data/mysql-5.7.31/temp/mysql.sock
root     11431 11135  0 07:55 pts/0    00:00:00 grep mysql

[root@localhost shell]# pgrep mysql
3198
4286

pstree

使用"树"形式列出当前执行的进程。-p 选项显示 PID和进程名字。

top

连续不断的显示 cpu 使用率最高的进程。-b 选项将会以文本方式显示,以便于可以在脚本中分析或存取。

nice

使用修改后的优先级来运行一个后台作业。优先级从 19(最低)到-20(最高)。只有 root 用户可以设置负的(比较高的)优先级。相关的命令是 renice、snice 和 skill。

nohup

保持一个命令的运行,即使用户登出系统。这个命令做为前台进程来运行,除非前边加 &。如果你在脚本中使用 nohup 命令,最好和 wait 命令一起使用,这样可以避免创建一个孤儿进程或僵尸进程。

pidof

取得一个正在运行的作业的进程 ID(PID)。因为一些作业控制命令,比如 kill 和 renice 只能使用进程的 PID(而不是它的名字),所以有时候必须的取得 PID。pidof 命令与$PPID 内部变量非常相似。

Example 13-6 pidof 帮助杀掉一个进程

#!/bin/bash
#
NOPROCESS=2
process=xxxyyyzzz
t=`pidof $process`

if [ -z "$t" ];then
  echo "Process $process was not running."
  echo "Nothing killed."
  exit $NOPROCESS
fi

kill $t  
exit 0
#整个脚本都可以使用下边这句来替换:
    #kill $(pidof -x process_name)

fuser

取得一个正在存取某个或某些文件(或目录)的进程 ID。使用-k 选项将会杀掉这些进程。对于系统安全来说,尤其是在脚本中想阻止未被授权的用户存取系统服务的时候,这个命令就显得很有用了。

[root@localhost shell]# fuser -u /usr/bin/vim
/usr/bin/vim:        11519e(root)

当正常的插入或删除保存的媒体,比如 CDROM 或者 USB 闪存设备的时候,fuser 的应用也显得特别重要。有时候当你想 umount 一个设备失败的时候(出现设备忙的错误消息), 这意味着某些用户或进程正在存取这个设备。使用 fuser -um /dev/device_name 可以搞定这些,这样你就可以杀掉所有相关的进程。

[root@localhost shell]# umount /mnt/usbdrive
umount: /mnt/usbdrive: device is busy
[root@localhost shell]# fuser -um /dev/usbdrive
[root@localhost shell]# /mnt/usbdrive: 1772c(bozo)
[root@localhost shell]# kill -9 1772
[root@localhost shell]# umount /mnt/usbdrive

fuser 的-n 选项可以获得正在存取某一端口的进程。当和 nmap 命令组合使用的时候尤其有用。

[root@localhost shell]# nmap localhost.localdomain
PORT STATE SERVICE
25/tcp open smtp
[root@localhost shell]# fuser -un tcp 25
25/tcp: 2095(root)
[root@localhost shell]# ps ax | grep 2095 | grep -v grep 2095 ? Ss 0:00 sendmail: accepting connections

cron

管理程序调度器,执行一些日常任务。比如清除和删除系统 log 文件, 或者更新 slocate 命令的数据库。这是 at 命令的超级用户版本(虽然每个用户都可以有自己的 crontab 文件,并且这个文件可以使用 crontab 命令来修改)。它以幽灵进程 T 的身份来运行,并且从 /ect/crontab 中获得执行的调度入口。

注意: 一些 Linux 的风格都使用 crond,Matthew Dillon 的 cron。

进程控制和启动类

init

init 命令是所有进程的父进程。在系统启动的最后一步调用 init 将会依据 /etc/inittab 来决定系统的运行级别。只能使用 root 身份来运行它的别名 telinit。

telinit

init 命令的符号链接,这是一种修改系统运行级别的一个手段,通常在系统维护或者紧急的文件系统修复的时候才用。只能使用 root 身份调用。调用这个命令是非常危险的在你使用之前确定你已经很好地了解它。

runlevel

显示当前和最后的运行级别。也就是确定你的系统是否终止(runlevel 为 0),还是运行 在单用户模式(1)、多用户模式(2)或者是运行在 X Windows(5),还是正在重启(6)。这 个命令将会存取/var/run/utmp 文件。

halt,shutdown,reboot

设置系统关机的命令,通常比电源关机的优先级高。

service

开启或停止一个系统服务。启动脚本在/etc/init.d 中,并且/etc/rc.d 在系统启动的时候使用这个命令来启动服务。

网络类

ifconfig

网络的接口配置和调试工具。
ifconfig 命令绝大多数情况都是在启动时候设置接口或者在重启的时候关闭它们。

#来自于 /etc/rc.d/init.d/network 的代码片段
#检查网络是否启动.
[ ${NETWORKING} = "no" ] && exit 0
[ -x /sbin/ifconfig ] || exit 0
...
for i in $linterfaces
do
  if ifconig $i 2>/dev/null | grep -q "UP";then
    action "Shutting down interface $i:" ./ifdown $i boot
  fi
echo "Currently active devices:"
echo `/sbin/ifconfig | grep ^[a-z] | awk '{print $1}'`

参见Example 29-6

iwconfig

这是为了配置无线网络的命令集合。可以说是上边的 ifconfig 的无线版本。

route

显示内核路由表信息,或者查看内核路由表的修改。

chkconfig

检查网络配置。这个命令负责显示和管理在启动过程中所开启的网络服务(这些服务都是 从/etc/rc?.d 目录中开启的)。
最开始是从 IRIX 到 Red Hat Linux 的一个接口,chkconfig 在某些 Linux 发行版中并不是核心安装的一部分。

tcpdump

网络包的"嗅探器"。这是一个用来分析和调试网络上传输情况的工具,它所使用的手段是把匹配指定规则的包头都显示出来。
显示主机 bozoville 和主机 caduceus 之间所有传输的 ip 包。

当然,tcpdump 的输出可以被分析,可以用我们之前讨论的文本处理工具来分析结果。

文件系统类

mount

加载一个文件系统,通常都用来安装外部设备,比如软盘或 CDROM。文件/etc/fstab 将会提供一个方便的列表,这个列表列出了所有可用的文件系统、分区和设备,另外还包括某些选项,比如是否可以自动或者手动的 mount。文件/etc/mtab 显示了当前已经 mount 的文件系统和分区(包括虚拟的, 比如/proc)。

mount -a 将会 mount 所有列在/ect/fstab 中的文件系统和分区,除了那些标记有非自动选项的。在启动的时候,在/etc/rc.d 中的一个启动脚本(rc.sysinit 或者一些相似的脚本) 将会这么调用,mount 所有可用的文件系统和分区。

这个多功能的命令甚至可以将一个普通文件 mount 到块设备中,并且这个文件就好像一个文件系统一样。mount 可以将文件与一个 loopback 设备相关联来达到这个目的。通过将文件与环回设备关联来实现这一点。这种应用通常都是用来 mount 和检查一个 ISO9660 镜像,在这个镜像被烧录到 CDR 之前。

Example 13-7 检查一个CD镜像

#!/bin/bash
#
mkdir /mnt/cdtest
mount -r -t iso9660 -o loop cd-image.iso /mnt/cdtest
cd /mnt/cdtest
ls -alR

umount

卸除一个当前已经 mount 的文件系统。在正常删除之前已经 mount 的软盘和 CDROM 之前,这个设备必须被 unmount,否则文件系统将会损坏。

sync

强制写入所有需要更新的 buffer 上的数据到硬盘上(同步带有 buffer 的驱动器)。如果不是严格必要的话,一个 sync 就可以保证系统管理员或者用户刚刚修改的数据会安全的在突然的断点中幸存下来。在比较早以前,在系统重启前都是使用 sync;sync (两次, 这样保证绝对可靠),这是一种很有用的小心的方法。

有时候,比如当你想安全删除一个文件的时候(参见 Example 12-55),或者当磁盘灯开始闪烁的时候,你可能需要强制马上进行 buffer 刷新。

losetup

建立和配置 loopback 设备。

Example 13-8 在一个文件中创建文件系统

#!/bin/bash
#
SIZE=1000000   #1M
head -c $SIZE < /dev/zero > file   # 建立指定尺寸的文件.
losetup /dev/loop0 file   # 作为 loopback 设备来建立.
mke2fs /dev/loop0   # 创建文件系统.
mount -o loop /dev/loop0 /mnt

mkswap

创建一个交换分区或文件。交换区域随后必须马上使用 swapon 来使能。

swapon,swapoff

使能/禁用 交换分区或文件。这两个命令通常在启动和关机的时候才有效。

mke2fs

创建 Linux ext2 文件系统。 这个命令必须以 root 身份调用。

tune2fs

调整 ext2 文件系统。可以用来修改文件系统参数,比如 mount 的最大数量。必须以 root 身份调用。

注意: 这是一个非常危险的命令。如果坏了,你需要自己负责,因为它可能会破坏你的文件系统。

dumpe2fs

打印(输出到 stdout 上)非常详细的文件系统信息。必须以 root 身份调用。

hdparm

列出或修改硬盘参数。这个命令必须以 root 身份调用,如果滥用的话会有危险。

fdisk

在存储设备上(通常都是硬盘)创建和修改一个分区表。必须以 root 身份使用。

注意: 谨慎使用这个命令。如果出错,会破坏你现存的文件系统。

fsck,e2fsck,debugfs

文件系统的检查、修复和除错命令集合。
fsck: 检查 UNIX 文件系统的前端工具(也可以调用其它的工具)。文件系统的类型一般都是默认的 ext2。

e2fsck: ext2 文件系统检查器。

debugfs: ext2 文件系统除错器。这个多功能但是危险的工具的用处之一就是(尝试)恢复删除的文件。只有高级用户才能用。

上边的这几个命令都必须以 root 身份调用,这些命令都很危险,如果滥用的话会破坏文件系统。

badblocks

检查存储设备的坏块(物理损坏)。这个命令在格式化新安装的硬盘时或者测试备份的完整性的时候会被用到。举个例子, badblocks /dev/fd0 测试一个软盘。

badblocks 可能会引起比较糟糕的结果(覆盖所有数据),在只读模式下就不会发生这种情况。如果 root 用户拥有需要测试的设备(通常都是这种情况),那么 root 用户必须调用这个命令。

lsusb,usbmodules

lsusb 命令会列出所有 USB(Universal Serial Bus 通用串行总线)总线和使用 USB 的设备。

usbmodules 命令会输出连接 USB 设备的驱动模块的信息。

[root@localhost shell]# lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 002 Device 002: ID 0627:0001 Adomax Technology Co., Ltd 

mkbootdisk

创建启动软盘,启动盘可以唤醒系统,比如当 MBR(master boot record 主启动记录)坏掉的时候。mkbootdisk 命令其实是一个 Bash 脚本,由 Erik Troan 所编写,放在/sbin 目录中。

chroot

修改 ROOT 目录。一般的命令都是从$PATH 中获得的,相对的默认的根目录是 /。这个命令将会把根目录修改为另一个目录(并且也将把工作目录修改到那)。出于安全目的时,这个命令非常有用的, 举个例子,当系统管理员希望限制一些特定的用户,比如 telnet 上来的用户,将他们限定到文件系统上一个安全的地方(这有时候被称为将一个 guest 用户限制在 "chroot 监牢"中)。注意:在使用 chroot 之后,系统的二进制可执行文件的目录将不再可用了。

注意: 由于正常的$PATH 将不再被关联了,所以可能需要将一些特定的系统文件拷贝到 chrooted 目录中。

lockfile

这个工具是 procmail 包的一部分(www.procmail.org)。它可以创建一个锁定文件,锁定文件是一种用来控制存取文件、设备或资源的标记文件。锁定文件就像一个标记一样被使用,如果特定的文件、设备或资源正在被一个特定的进程所使用(“busy”),那么对于其它进程来说,就只能受限进行存取(或者不能存取)。

一般情况下,应用创建或检查锁定文件都放在/var/lock 目录中。脚本可以使用下面的方法来检测锁定文件是否存在。

appname=xyzip
if [ -e "/var/lock/$appname.lock" ];then
...

mknod

创建块或者字符设备文件(当在系统上安装新硬盘时可能是必要的)。MAKEDEV 工具事实上具有 nknod 的全部功能,而且更容易使用。

MAKEDEV

创建设备文件的工具。必须在/dev 目录下,并且以 root 身份使用。

tmpwatch

自动删除在指定时间内未被存取过的文件。通常都是被 cron 调用,用来删掉老的 log 文件。

备份类

dump,restore

dump 命令是一个精巧的文件系统备份工具,通常都用在比较大的安装和网络上。它读取原始的磁盘分区并且以二进制形式来写备份文件。需要备份的文件可以保存到各种各样的存储设备上,包括磁盘和磁带。restore 命令用来恢复 dump 所产生的备份。

fdformat

对软盘进行低级格式化。

系统资源类

ulimit

设置使用系统资源的上限。通常情况下都是使用-f 选项来调用,-f 用来设置文件尺寸的限制(ulimit -f 1000 就是将文件大小限制为 1M)。-c 选项来限制 coredump(核心转储, 程序崩溃时的内存状态写入文件) 尺寸(ulimit -c 0 就是不要 coredumps)。一般情况下,ulimit 的值应该设置在 /etc/profile 和(或)~/.bash_profile 中(参见 Appendix G)。

注意: 明智的使用 ulimit 可以保护系统免受可怕的 fork 炸弹的迫害。

quota

显示用户或组的磁盘配额

setquota

从命令行中设置用户或组的磁盘配额

umask

设定用户创建文件时权限的缺省 mask(掩码)。也可以用来限制特定用户的默认文件属性。所有用户创建的文件属性都是由 umask 所指定的。
用户一般都是将 umask 设置值的地方放在/etc/profile 和(或) ~/.bash_profile 中 (参见 Appendix G)。

Example 13-10 使用umask来将输出文件隐藏起来

#!/bin/bash
#
umask 177   #文件掩码,被这个脚本所创建的文件将具有600权限
OUTFILE=decrypted.txt

cat "$@" | tr 'a-zA-z' 'n-za-mN-ZA-M' > $OUTFILE
exit 0

rdev

取得 root device、swap space 或 video mode 的相关信息,或者对它们进行修改。通常说来 rdev 都是被 lilo 所使用,但是在建立一个 ram disk 的时候,这个命令也很有用。小心使用,这是一个危险的命令。

模块类

lsmod

列出所有安装的内核模块。

[root@localhost shell]# lsmod 
Module                  Size  Used by
iptable_filter          2793  0 
ip_tables              17831  1 iptable_filter
...
pata_acpi               3701  0 
ata_generic             3837  0 
ata_piix               24601  0 
dm_mirror              14384  0 
dm_region_hash         12085  1 dm_mirror
dm_log                  9930  2 dm_mirror,dm_region_hash
dm_mod                 84209  8 dm_mirror,dm_log

注意: 使用 cat /proc/modules 可以得到同样的结果。

insmod

强制一个内核模块的安装(如果可能的话,使用 modprobe 来代替) 必须以 root 身份调用。

rmmod

强制卸载一个内核模块。必须以 root 身份调用。

modprobe

模块装载器,一般情况下都是在启动脚本中自动调用。必须以 root 身份调用。

depmod

创建模块依赖文件,一般都是在启动脚本中调用。

modinfo

输出一个可装载模块的信息。

杂项类

evn

使用设置过的或修改过(并不是修改整个系统环境)的环境变量来运行一个程序或脚本。使用 [varname=xxx] 形式可以在脚本中修改环境变量。如果没有指定参数,那么这个命令将会列出所有设置的环境变量。

注意: 在 Bash 和其它的 Bourne shell 衍生物中,是可以在单一命令行上设置多个变量的。

注意: 当不知道 shell 或解释器的路径的时候,脚本的第一行(#!行)可以使用 env。

#!/usr/bin/env perl
#
printf "This Perl script will run,\n";
print "even when I don't know where to find Perl.\n";

ldd

显示一个可执行文件的共享库的依赖关系。

[root@localhost shell]# ldd /bin/ls
	linux-vdso.so.1 =>  (0x00007fffbafff000)
	libselinux.so.1 => /lib64/libselinux.so.1 (0x00000031ffa00000)
	librt.so.1 => /lib64/librt.so.1 (0x0000003977c00000)
	libcap.so.2 => /lib64/libcap.so.2 (0x0000003979800000)
	libacl.so.1 => /lib64/libacl.so.1 (0x000000397c400000)
	libc.so.6 => /lib64/libc.so.6 (0x0000003977400000)
	libdl.so.2 => /lib64/libdl.so.2 (0x0000003977000000)
	/lib64/ld-linux-x86-64.so.2 (0x0000003976c00000)
	libpthread.so.0 => /lib64/libpthread.so.0 (0x0000003977800000)
	libattr.so.1 => /lib64/libattr.so.1 (0x000000397a000000)

watch

以指定的时间间隔来重复运行一个命令。默认的时间间隔是 2 秒,但时刻以使用-n 选项来修改。

strip

从可执行文件中去掉调试符号引用。这样做可以减小尺寸,但是就不能调试了。

这个命令一般都用在 Makefile 中,但是很少用在 shell 脚本中。

nm

列出未 strip 过的编译后的 2 进制文件的符号。

rdist

远程文件分布客户机程序: 在远端服务器上同步、克隆或者备份一个文件系统。

13.1 分析一个系统脚本

利用我们所学到的关于管理命令的知识,让我们一起来练习分析一个系统脚本。最简单并 且最短的系统脚本之一是 killall,这个脚本被用来在系统关机时挂起运行的脚本。

Example 13-11 killall,来自/etc/rc.d/init.d

#!/bin/sh
#
for i in /var/lock/subsys/*;do
  [ ! -f $i ] && continue
  subsys=${i#/var/lock/subsys/}   #subsys=`basename $i`完全等价.
  #从锁定文件名中获得,(如果那里有锁定文件的话, 那就证明进程正在运行).
  if [ -f /etc/rc.d/init.d.$subsys.init ];then
    /etc/rc.d/init.d/$subsys.ini stop
  esle
    /etc/rc.d/init.d/$subsys.init stop
  fi
done

你可能感兴趣的:(Shell)