Unix Toolbox - 中文版

Table of Contents

1. 介绍

这是一份收集Unix/Linux/BSD命令和任务的文档, 它有助于高级用户或IT工作. 它是一份简明扼要的实用指南, 当然读者应该知道他/她在干什么.

Unix Toolbox 版本: 12 你可以到 本文档的最新版 找到. PDF版本可以替换链接中的.xhtml为 .pdf , 小册子版本可以替换成 .book.pdf . 用双面打印机可将小册子打印成册. 这份XHTML页面可以通过CSS3相兼容的应用程序转换成一份漂亮的PDF文档(看 脚本例子).

错误报告和评论是最欢迎的 - c@cb.vu Colin Barschel. 你可以到中文最新版找到. 也可到我的主页获取http://silenceisdefeat.org/~greco/unixtoolbox_zh_CN.xhtml 关于中文版的任何错误和修正请发送E-Mail到 ]>

© Colin Barschel and Greco Shi 2007-2008. Some rights reserved under Creative Commons.

2. 系统

2.1. 正在运行的内核和系统信息

# uname -a                           # 获取内核版本(和BSD版本)
# lsb_release -a                     # 显示任何 LSB 发行版版本信息
# cat /etc/SuSE-release              # 获取 SuSE 版本
# cat /etc/debian_version            # 获取 Debian 版本
# uptime                             # 显示系统开机运行到现在经过的时间
# hostname                           # 显示系统主机名
# hostname -i                        # 显示主机的 IP 地址
# man hier                           # 描述文件系统目录结构
# last reboot                        # 显示系统最后重启的历史记录

2.2. 硬件信息

2.2.1. 内核检测到的硬件信息

# dmesg                              # 检测到的硬件和启动的消息
# lsdev                              # 关于已安装硬件的信息
# dd if=/dev/mem bs=1k skip=768 count=256 2>/dev/null | strings -n 8 # 读取 BIOS 信息

2.2.2. Linux

# cat /proc/cpuinfo                  # CPU 讯息
# cat /proc/meminfo                  # 内存信息
# grep MemTotal /proc/meminfo        # 显示物理内存大小
# watch -n1 'cat /proc/interrupts'   # 监控内核处理的所有中断
# free -m                            # 显示已用和空闲的内存信息 (-m 为 MB)
# cat /proc/devices                  # 显示当前核心配置的设备
# lspci -tv                          # 显示 PCI 设备
# lsusb -tv                          # 显示 USB 设备
# lshal                              # 显示所有设备属性列表
# dmidecode                          # 显示从 BIOS 中获取的硬件信息

2.2.3. FreeBSD

# sysctl hw.model                    # CPU 讯息
# sysctl hw                          # 得到很多硬件信息
# sysctl vm                          # 虚拟内存使用情况
# dmesg | grep "real mem"            # 物理内存
# sysctl -a | grep mem               # 内核内存的设置和信息
# sysctl dev                         # 显示当前核心配置的设备
# pciconf -l -cv                     # 显示 PCI 设备
# usbdevs -v                         # 显示 USB 设备
# atacontrol list                    # 显示 ATA 设备

2.3. 显示状态信息

以下的命令有助于找出正在系统中运行着的程序.

# top                                # 显示和更新使用 cpu 最多的进程
# mpstat 1                           # 显示进程相关的信息
# vmstat 2                           # 显示虚拟内存的状态信息
# iostat 2                           # 显示 I/O 状态信息(2 秒 间隙)
# systat -vmstat 1                   # 显示 BSD 系统状态信息(1 秒 间隙)
# systat -tcp 1                      # 显示 BSD TCP 连接信息(也可以试试 -ip)
# systat -netstat 1                  # 显示 BSD 当前网络连接信息
# systat -ifstat 1                   # 显示 BSD 当前网卡带宽信息
# systat -iostat 1                   # 显示 BSD CPU 和磁盘使用情况
# tail -n 500 /var/log/messages      # 显示最新500条内核/系统日志的信息
# tail /var/log/warn                 # 显示系统警告信息(看syslog.conf)

2.4. 用户

# id                                 # 显示当前用户和用户组的 ID
# last                               # 列出目前与过去登入系统的用户相关信息
# who                                # 显示目前登入系统的用户信息
# groupadd admin                     # 建立新组"admin"和添加新用户 colin 并加入 admin 用户组(Linux/Solaris)
# useradd -c "Colin Barschel" -g admin -m colin
# userdel colin                      # 删除用户 colin(Linux/Solaris)
# adduser joe                        # FreeBSD 添加用户 joe(交互式)
# rmuser joe                         # FreeBSD 删除用户 joe(交互式)
# pw groupadd admin                  # 在 FreeBSD 上使用 pw
# pw groupmod admin -m newmember     # 添加新用户到一个组
# pw useradd colin -c "Colin Barschel" -g admin -m -s /bin/tcsh
# pw userdel colin; pw groupdel admin

加密过的密码存储在 /etc/shadow (Linux and Solaris) 或 /etc/master.passwd (FreeBSD) 中. 如果手动修改了 master.passwd, 需要运行 # pwd_mkdb -p master.passwd 来重建数据库. 使用 nologin 来临时阻止所有用户登录(root除外). 用户登录时将会显示 nologin 中的信息.

# echo "Sorry no login now" > /etc/nologin       # (Linux)
# echo "Sorry no login now" > /var/run/nologin   # (FreeBSD)

2.5. 限制

某些应用程序需要设置可打开最大文件和 socket 数量(像代理服务器, 数据库). 默认限制通常很低.

2.5.1. Linux

  1. 每 shell/脚本

    shell 的限制是受 ulimit 支配的. 使用 ulimit -a 可查看其状态信息. 举个例子, 改变可打开最大文件数从 1024 到 10240, 可以这么做:

    # ulimit -n 10240                    # 这只在shell中有用
    

    ulimit 命令可以使用在脚本中来更改对此脚本的限制.

  2. 每 用户/进程

    登录用户和应用程序的限制可以在 /etc/security/limits.conf 中配置. 举个例子:

    # cat /etc/security/limits.conf
     *   hard    nproc   250              # 限制所有用户进程数
    asterisk hard nofile 409600          # 限制应用程序可打开最大文件数
    
  3. 系统级

    用sysctl来设置内核限制. 要使其永久, 可以在 /etc/sysctl.conf 中进行配置.

    # sysctl -a                          # 显示所有系统限制
    # sysctl fs.file-max                 # 显示系统最大文件打开数
    # sysctl fs.file-max=102400          # 更改系统最大文件打开数
    # cat /etc/sysctl.conf
    fs.file-max=102400                   # 在 sysctl.conf 中的永久项
    # cat /proc/sys/fs/file-nr           # 在使用的文件句柄数
    

2.5.2. FreeBSD

  1. 每 shell/脚本

    在 csh 或 tcsh 中使用 limits 命令, 在 sh 或 bash 中使用 ulimit 命令.

  2. 每 用户/进程

    /etc/login.conf 中配置登录后的默认限制. 未作限制的值为系统最大限制值.

  3. 系统级

    内核限制同样使用 sysctl 来设置. 永久配置, 在 /etc/sysctl.conf/boot/loader.conf 中. 其语法与 Linux 相同, 只是键值不同.

    # sysctl -a                          # 显示所有系统限制
    # sysctl kern.maxfiles=XXXX          # 最大文件描述符数
    

    /etc/sysctl.conf 中的永久项:

    kern.ipc.nmbclusters=32768
    kern.maxfiles=65536                  # Squid 通常用这个值
    kern.maxfilesperproc=32768
    kern.ipc.somaxconn=8192              # TCP 列队. apache/sendmail 最好用这个值
    
    # sysctl kern.openfiles              # 在使用的文件描述符数
    # sysctl kern.ipc.numopensockets     # 已经开启的 socket 数目
    

    详情请看 FreeBSD 手册 11章.

2.5.3. Solaris

/etc/system 中的下列设置, 会提高每个进程可以打开最大文件描述符的数量:

set rlim_fd_max = 4096               # 一个进程可以打开文件描述符的"硬"限制
set rlim_fd_cur = 1024               # 一个进程可以打开文件描述符的"软"限制

2.6. 运行级别

2.6.1. Linux

一旦内核加载完成, 内核会启动 init 进程, 然后运行 rc 脚本, 之后运行所有属于其运行级别的命令脚本. 这些脚本都储存在 /etc/rc.d/rcN.d 中(N代表运行级别), 并且都建立着到 /etc/init.d 子目录中命令脚本程序的符号链接. 默认运行级别配置在 /etc/inittab 中. 它通常为 3 或 5:

# grep default: /etc/inittab
id:3:initdefault:

可以使用 init 来改变当前运行级别. 举个例子:

# init 5                             # 进入运行级别 5

运行级别列表如下:

0
系统停止
1
进入单用户模式(也可以是 S)
2
没有 NFS 特性的多用户模式
3
完全多用户模式(正常操作模式)
4
未使用
5
类似于级别3, 但提供 XWindow 系统登录环境
6
重新启动系统

使用 chkconfig 工具控制程序在一个运行级别启动和停止.

# chkconfig --list                   # 列出所有 init 脚本
# chkconfig --list sshd              # 查看 sshd 在各个运行级别中的启动配置
# chkconfig sshd --level 35 on       # 对 sshd 在级别 3 和 5 下创建启动项
# chkconfig sshd off                 # 在所有的运行级别下禁用 sshd

Debian 和基于Debian 发行版像 Ubuntu 或 Knoppix 使用命令 update-rc.d 来管理运行级别脚本. 默认启动为 2,3,4 和 5, 停止为 0,1 和 6.

# update-rc.d sshd defaults          # 设置 sshd 为默认启动级别
# update-rc.d sshd start 20 2 3 4 5 . stop 20 0 1 6 .  # 用显示参数
# update-rc.d -f sshd remove         # 在所有的运行级别下禁用 sshd
# shutdown -h now (或者 # poweroff)  # 关闭停止系统

2.6.2. FreeBSD

BSD 启动步骤不同于 SysV, 她没有运行级别. 她的启动状态(单用户, 有或没有 XWindow)被配置在 /etc/ttys 中. 所有的系统脚本都位于 /etc/rc.d/=中, 第三方应用程序位于 =/usr/local/etc/rc.d/=中. service 的启动顺序被配置在 =/etc/rc.conf 和=/etc/rc.conf.local=中. 默认行为可在 /etc/defaults/rc.conf 中进行配置. 这些脚本至少响应 start|stop|status.

# /etc/rc.d/sshd status
sshd is running as pid 552.
# shutdown now                       # 进入单用户模式
# exit                               # 返回到多用户模式
# shutdown -p now                    # 关闭停止系统
# shutdown -r now                    # 重新启动系统

同样可以使用进程 init 进入下列状态级别. 举个例子: # init 6 为重启.

0
停止系统并关闭电源 (信号 USR2)
1
进入单用户模式 (信号 TERM)
6
重新启动 (信号 INT)
c
阻止进一步登录 (信号 TSTP)
q
重新检查 ttys(5) 文件 (信号 HUP)

2.7. 重设 root 密码

2.7.1. Linux 方法 1

在引导加载器(lilo 或 grub)中, 键入如下启选项:

init=/bin/sh

内核会挂载 root 分区, 进程 init 会启动 bourne shell 而不是 rc, 然后是运行级别. 使用命令 passwd 设置密码然后重启. 别忘了需要在单用户模式下做这些动作. 如果重启后 root 分区被挂载为只读, 重新挂在它为读写:

# mount -o remount,rw /
# passwd                             # 或者删除 root 密码 (/etc/shadow)
# sync; mount -o remount,ro /        # sync 在重新挂在为只读之前 sync 一下
# reboot

2.7.2. FreeBSD 和 Linux 方法 2

FreeBSD 不会让你这么做. 解决方案是用其他操作系统(像系统紧急修复光盘)挂载 root 分区, 然后更改密码. 用 live cd 或安装盘启动进入修复模式后, 会得到一个 shell. 用 fdisk 查找 root 分区. 比如: fdisk /dev/sda 挂载它并使用 chroot 命令:

# mount -o rw /dev/ad4s3a /mnt
# chroot /mnt                        # 改变程序执行时所参考的根目录位置为 /mnt
# passwd
# reboot

2.8. 内核模块

2.8.1. Linux

# lsmod                              # 列出所有已载入内核的模块
# modprobe isdn                      # 载入 isdn 模块

2.8.2. FreeBSD

# kldstat                            # 列出所有已载入内核的模块
# kldload crypto                     # 载入 crypto 模块

2.9. 编译内核

2.9.1. Linux

# cd /usr/src/linux
# make mrproper                      # 清除所有东西, 包括配置文件
# make oldconfig                     # 从当前内核配置文件的基础上创建一个新的配置文件
# make menuconfig                    # 或者 xconfig (Qt) 或者 gconfig (GTK)
# make                               # 创建一个已压缩的内核映像文件
# make modules                       # 编译模块
# make modules_install               # 安装模块
# make install                       # 安装内核
# reboot

2.9.2. FreeBSD

要改变和重建内核, 需要拷贝源配置文件然后编辑它. 当然也可以直接编辑 GENERIC 文件.

# cd /usr/src/sys/i386/conf/
# cp GENERIC MYKERNEL
# cd /usr/src
# make buildkernel KERNCONF=MYKERNEL
# make installkernel KERNCONF=MYKERNEL

要重建完全的操作系统:

# make buildworld                    # 构建完全的系统, 但不是内核
# make buildkernel                   # 使用 KERNCONF 配置文件编译内核
# make installkernel
# reboot
# mergemaster -p                     # 建立临时根环境并比对系统配置文件
# make installworld
# mergemaster                        # 升级所有配置和其他文件
# reboot

对于源的一些小改动, 有时候简单的命令就足够了:

# make kernel world                  # 编译并安装内核和系统
# mergemaster
# reboot

3. 进程

3.1. 进程列表

PID是每个进程唯一号码. 使用 ps 获取所有正在运行的进程列表.

# ps -auxefw                         # 所有正在运行进程的详尽列表
# ps axww | grep cron
# ps aux | grep 'ss[h]'              # Find all ssh pids without the grep pid
# pgrep -l sshd                      # 查找所有进程名中有sshd的进程ID
# echo $$                            # The PID of your shell
# fuser -va 22/tcp                   # 列出使用端口22的进程
# fuser -va /home                    # 列出访问 /home 分区的进程
# strace df                          # 跟踪系统调用和信号
# truss df                           # 同上(FreeBSD/Solaris/类Unix)
# history | tail -50                 # 显示最后50个使用过的命令

3.2. 优先级

用 renice 更改正在运行进程的优先级. 负值是更高的优先级, 最小为-20, 其正值与 "nice" 值的意义相同.

# renice -5 586                      # 更强的优先级

使用 nice 命令启动一个已定义优先级的进程. 正值为低优先级, 负值为高优先级.

# nice -n -5 top                     # 更高优先级(/usr/bin/nice)
# nice -n 5 top                      # 更低优先级(/usr/bin/nice)
# nice +5 top                        # tcsh 内置 nice 命令(同上)

ionice 可以调度磁盘 IO.

# ionice c3 -p123                    # 给 pid 123 设置为 idle 类型
# ionice -c2 -n0 firefox             # 用 best effort 类型运行 firefox 并且设为高优先级
# ionice -c3 -p$$                    # 将当前的进程(shell)的磁盘 IO 调度设置为 idle 类型

3.3. 前台/后台

当一个进程在 shell 中已运行, 可以使用 [Ctrl]-[Z] (^Z), bgfg 来 调入调出前后台.

# ping cb.vu > ping.log

^Z (使用 [Ctrl]-[Z] 来暂停)

# bg                                 # 调入后台继续运行
# jobs -l                            # 后台进程列表
# fg %2                              # 让进程 2 返回到前台运行

使用 nohup 开启一个持续运行的进程直到 shell 被关闭(避免挂断).

# nohup ping -i 60 > ping.log &

3.4. Top

top 程序用来实时显示系统中各个进程的运行信息.

# top

当 top 在运行的时候, 按下 h 键会显示帮助画面. 常用键如下:

u [用户名]
只显示属于此用户的进程. 使用 + 或者空白可以查看所有用户
k [PID]
结束 PID 进程
1
显示所有进程状态信息(只有Linux)
R
将当前排序倒转

3.5. Kill命令与信号

使用 kill 或 killall 终止或发送一个信号给进程.

# ping -i 60 cb.vu > ping.log &
# kill -s TERM 4712                  # 同 kill -15 4712
# killall -1 httpd                   # 发送 HUP 信号终止进程 httpd
# pkill -9 http                      # 发送 TERM 信号终止包含 http 的进程
# pkill -TERM -u www                 # 发送 TERM 信号终止 www 所有者进程
# fuser -k -TERM -m /home            # 终止所有访问 /home 的进程(卸载该分区前)

下面是一些重要的信号:

1
HUP (挂起)
2
INT (中断)
3
QUIT (退出)
9
KILL (KILL 信号不能被捕捉, 不能被忽略. )
15
TERM (软件终止信号)

4. 文件系统

4.1. 权限

用 chmod 和 chown 更改访问权限和所有权. 对于所有用户的默认掩码(umask)可以在 /etc/profile (Linux) 或 /etc/login.conf (FreeBSD) 中修改.

  • 1 –x 执行
  • 2 -w- 写
  • 4 r– 读
# chmod [OPTION] MODE[,MODE] FILE    # MODE 可以是 [ugoa]*([-+=]([rwxXst]))
# chmod 640 /var/log/maillog         # 更改 maillog 访问权限为 -rw-r-----
# chmod u=rw,g=r,o= /var/log/maillog # 同上
# chmod -R o-r /home/*               # 递归去除所有其他用户的可读权限
# chmod u+s /path/to/prog            # 在可执行位设置 SUID (知道你在干什么!)
# find / -perm -u+s -print           # 查找所有设置过 SUID 位的程序
# chown user:group /path/to/file     # 改变文件的所有者和文件关联的组
# chgrp group /path/to/file          # 改变文件关联的组
# chmod 640 `find ./ -type f -print` # Change permissions to 640 for all files
# chmod 751 `find ./ -type d -print` # Change permissions to 751 for all directories

4.2. 磁盘信息

# diskinfo -v /dev/ad2               # 显示磁盘信息(扇区/大小) (FreeBSD)
# hdparm -I /dev/sda                 # 显示 IDE/ATA 磁盘信息 (Linux)
# fdisk /dev/ad2                     # 显示和修改磁盘分区表
# smartctl -a /dev/ad2               # 显示磁盘检测信息

4.3. Boot

4.3.1. FreeBSD

如果新内核不能引导, 要引导一个旧内核, 停止启动倒计时, 做如下动作:

# unload
# load kernel.old
# boot

4.4. 系统挂载点/磁盘使用情况

# mount | column -t                  # 显示系统已挂载分区情况
# df                                 # 显示磁盘剩余空间和挂载的设备
# cat /proc/partitions               # 显示所有设备的所有分区(Linux)

4.5. 磁盘使用情况

# du -sh *                           # 列出当前目录下所有文件夹大小
# du -csh                            # 当前目录下所有目录大小总数
# du -ks * | sort -n -r              # 由大到小排序显示目录大小
# ls -lSr                            # 由小到大显示文件列表

4.6. 谁打开了那些文件

4.6.1. FreeBSD 和大多数 Unix

# fstat -f /home                     # 对于一个挂载点
# fstat -p PID                       # 对于一个应用程序进程 ID
# fstat -u user                      # 对于一个用户
# ps ax | grep Xorg | awk '{print $1}'
# fstat -p 1252
# find -x /var -inum 212042

4.6.2. Linux

# fuser -m /home                     # 列出访问 /home 的进程
# lsof /home
# ps ax | grep Xorg | awk '{print $1}'
# lsof -p 3324
# lsof /var/log/Xorg.0.log

4.7. 挂载/重挂载一个文件系统

举个 cdrom 的例子. 如果已经列于 /etc/fstab 中:

# mount /cdrom

4.7.1. FreeBSD

# mount -v -t cd9660 /dev/cd0c /mnt  # cdrom
# mount_cd9660 /dev/wcd0c /cdrom     # 另外一个方法
# mount -v -t msdos /dev/fd0c /mnt   # 软驱

/etc/fstab 中的一条:

# Device                Mountpoint      FStype  Options         Dump    Pass#
/dev/acd0               /cdrom          cd9660  ro,noauto       0       0

要允许用户做这些, 可以这么做:

# sysctl vfs.usermount=1  # 或者在 /etc/sysctl.conf 中插入一条 "vfs.usermount=1"

4.7.2. Linux

# mount -t auto /dev/cdrom /mnt/cdrom   # 典型的 cdrom 挂载命令
# mount /dev/hdc -t iso9660 -r /cdrom   # IDE
# mount /dev/sdc0 -t iso9660 -r /cdrom  # SCSI

/etc/fstab 中的条目:

/dev/cdrom   /media/cdrom  subfs noauto,fs=cdfss,ro,procuid,nosuid,nodev,exec 0 0

用 Linux 挂载一个 FreeBSD 分区

# fdisk /dev/sda                     # 查找 FreeBSD 分区
# mount -t ufs -o ufstype=ufs2,ro /dev/sda3 /mnt

4.7.3. 重挂载

# mount -o remount,ro /              # Linux
# mount -o ro /                      # FreeBSD

从 cdrom 拷贝原始数据进一个 iso 映像文件:

# dd if=/dev/cd0c of=file.iso

4.7.4. 给即时烧录(on-the-fly)添加 swap

假设你需要很多的 swap (即刻), 如一个 2GB 文件 /swap2gb (只限 Linux).

# dd if=/dev/zero of=/swap2gb bs=1024k count=2000
# mkswap /swap2gb                    # 创建交换区
# swapon /swap2gb                    # 激活这个 swap. 现在可以使用了
# swapoff /swap2gb                   # 当使用完毕, 释放这个 swap
# rm /swap2gb

4.8. 挂载一个 SMB 共享

4.8.1. Linux

# smbclient -U user -I 192.168.16.229 -L //smbshare/    # 列出共享
# mount -t smbfs -o username=winuser //smbserver/myshare /mnt/smbshare
# mount -t cifs -o username=winuser,password=winpwd //192.168.16.229/myshare /mnt/share

此外, mount.cifs 软件包可以存储认证到一个文件中. 例如, /home/user/.smb:

username=winuser
password=winpwd

现在可以像下面那样挂载:

# mount -t cifs -o credentials=/home/user/.smb //192.168.16.229/myshare /mnt/smbshare

4.8.2. FreeBSD

# smbutil view -I 192.168.16.229 //winuser@smbserver    # 列出共享
# mount_smbfs -I 192.168.16.229 //winuser@smbserver/myshare /mnt/smbshare

4.9. 挂载镜像文件

4.9.1. Linux loop-back

# mount -t iso9660 -o loop file.iso /mnt                # 挂载 CD 镜像文件
# mount -t ext3 -o loop file.img /mnt                   # 用 ext3 文件系统挂载镜像文件

4.9.2. FreeBSD

用于存储设备:

# mdconfig -a -t vnode -f file.iso -u 0
# mount -t cd9660 /dev/md0 /mnt
# umount /mnt; mdconfig -d -u 0                         # 清除 md 设备

用于虚拟节点:

# vnconfig /dev/vn0c file.iso; mount -t cd9660 /dev/vn0c /mnt
# umount /mnt; vnconfig -u /dev/vn0c                    # 清除 vn 设备

4.9.3. Solaris and FreeBSD

用于 loop-back 文件接口或 lofi:

# lofiadm -a file.iso
# mount -F hsfs -o ro /dev/lofi/1 /mnt
# umount /mnt; lofiadm -d /dev/lofi/1                   # 清除 lofi 设备

4.10. 创建并刻录 ISO 镜像文件

# dd if=/dev/hdc of=/tmp/mycd.iso bs=2048 conv=notrunc

使用 mkisofs 把目录中所有文件创建成 CD/DVD 镜像文件.

# mkisofs -J -L -r -V TITLE -o imagefile.iso /path/to/dir

4.11. 刻录 ISO 镜像文件

4.11.1. FreeBSD

FreeBSD 默认情况下没有在 ATAPI 驱动上启用 DMA.

# burncd -f /dev/acd0 data imagefile.iso fixate      # ATAPI 驱动
# cdrecord -scanbus                  # 查找 burner 设备描述符(如 1,0,0)
# cdrecord dev=1,0,0 imagefile.iso

4.11.2. Linux

# cdrecord dev=ATAPI -scanbus

然后同上面一样烧录 CD/DVD.

4.11.3. dvd+rw-tools

# growisofs -dvd-compat -Z /dev/dvd=imagefile.iso     # 刻录已存在的 iso 镜像文件
# growisofs -dvd-compat -Z /dev/dvd -J -R /p/to/data  # 直接刻录

4.11.4. 转换 Nero .nrg 文件成 .iso

# dd bs=1k if=imagefile.nrg of=imagefile.iso skip=300

4.11.5. 转换 bin/cue 镜像成 .iso

# bchunk imagefile.bin imagefile.cue imagefile.iso

4.12. 创建基于文件的镜像文件

4.12.1. FreeBSD

# dd if=/dev/random of=/usr/vdisk.img bs=1K count=1M
# mdconfig -a -t vnode -f /usr/vdisk.img -u 0         # 创建设备 /dev/md1
# bsdlabel -w /dev/md0
# newfs /dev/md0c
# mount /dev/md0c /mnt
# umount /mnt; mdconfig -d -u 0; rm /usr/vdisk.img    # 清除 md 设备

也可能在增加镜像文件的大小之后, 如增大到 300MB.

# umount /mnt; mdconfig -d -u 0
# dd if=/dev/zero bs=1m count=300 >> /usr/vdisk.img
# mdconfig -a -t vnode -f /usr/vdisk.img -u 0
# growfs /dev/md0
# mount /dev/md0c /mnt                                # 文件分区现在为 300MB

4.12.2. Linux

# dd if=/dev/zero of=/usr/vdisk.img bs=1024k count=1024
# mkfs.ext3 /usr/vdisk.img
# mount -o loop /usr/vdisk.img /mnt
# umount /mnt; rm /usr/vdisk.img                      # 清楚

4.12.3. Linux with losetup

# dd if=/dev/urandom of=/usr/vdisk.img bs=1024k count=1024
# losetup /dev/loop0 /usr/vdisk.img                   # 创建并联结 /dev/loop0
# mkfs.ext3 /dev/loop0
# mount /dev/loop0 /mnt
# losetup -a                                          # 查看已经挂载的 loop 设备
# umount /mnt
# losetup -d /dev/loop0                               # Detach
# rm /usr/vdisk.img

4.13. 创建基于内存的文件系统

4.13.1. FreeBSD

# mount_mfs -o rw -s 64M md /memdisk
# umount /memdisk; mdconfig -d -u 0                   # 清除该 md 设备

/etc/fstab 条目:

md     /memdisk     mfs     rw,-s64M    0   0

4.13.2. Linux

# mount -t tmpfs -osize=64m tmpfs /memdisk

4.14. 磁盘性能

# time dd if=/dev/ad4s3c of=/dev/null bs=1024k count=1000
# time dd if=/dev/zero bs=1024k count=1000 of=/home/1Gb.file
# hdparm -tT /dev/hda      # 仅限 Linux

5. 网络

5.1. 调试

5.1.1. Linux

# ethtool eth0              # 显示以太网状态(replaces mii-diag)
# ethtool -s eth0 speed 100 duplex full # 把网卡 eth0 速度改为 100兆/秒, 采用全双工
# ethtool -s eth0 autoneg off # 禁用自动协商模式
# ethtool -p eth1           # 闪烁网络接口 LED 灯 - 如果支持的话, 非常实用
# ip link show              # 在 Linux 上显示所有网络接口(同 ifconfig 类似)
# ip link set eth0 up       # 使设备激活(或Down掉). 同 "ifconfig eth0 up"
# ip addr show              # 在 Linux 上显示所有 IP 地址(与 ifconfig 类似)
# ip neigh show             # 与 arp -a 类似

5.1.2. 其他系统

# ifconfig fxp0             # 查看 "media" 字段(FreeBSD)
# arp -a                    # 查看路由(或主机) ARP 条目(所有系统)
# ping cb.vu                # 第一个要试的事情...
# traceroute cb.vu          # 列印到目的地的路由路径
# ifconfig fxp0 media 100baseTX mediaopt full-duplex # 100兆/秒 全双工(FreeBSD)
# netstat -s                # 对每个网络协议做系统级分析
# arping 192.168.16.254     # 在网络层上 Ping
# tcptraceroute -f 5 cb.vu  # 使用 tcp 替换 icmp 来跟踪, 透过防火墙

5.2. 路由

5.2.1. 列印路由表

# route -n                  # Linux 或使用 "ip route"
# netstat -rn               # Linux, BSD 和 UNIX
# route print               # Windows

5.2.2. 添加删除路由

  1. FreeBSD
    # route add 212.117.0.0/16 192.168.1.1
    # route delete 212.117.0.0/16
    # route add default 192.168.1.1
    

    永久的添加路由可在 /etc/rc.conf 配置文件中设置:

    static_routes="myroute"
    route_myroute="-net 212.117.0.0/16 192.168.1.1"
    
  2. Linux
    # route add -net 192.168.20.0 netmask 255.255.255.0 gw 192.168.16.254
    # ip route add 192.168.20.0/24 via 192.168.16.254       # 等同于上面命令
    # route add -net 192.168.20.0 netmask 255.255.255.0 dev eth0
    # route add default gw 192.168.51.254
    # ip route add default via 192.168.51.254 dev eth0      # 等同于上面命令
    # route delete -net 192.168.20.0 netmask 255.255.255.0
    
  3. Solaris
    # route add -net 192.168.20.0 -netmask 255.255.255.0 192.168.16.254
    # route add default 192.168.51.254 1                    # 1 = 通过此路由跳数减 1
    # route change default 192.168.50.254 1
    
  4. Windows
    # Route add 192.168.50.0 mask 255.255.255.0 192.168.51.253
    # Route add 0.0.0.0 mask 0.0.0.0 192.168.51.254
    

5.3. 配置额外的 IP 地址

5.3.1. Linux

# ifconfig eth0 192.168.50.254 netmask 255.255.255.0       # 第一个 IP
# ifconfig eth0:0 192.168.51.254 netmask 255.255.255.0     # 第二个 IP
# ip addr add 192.168.50.254/24 dev eth0                   # 等价命令
# ip addr add 192.168.51.254/24 dev eth0 label eth0:1

5.3.2. FreeBSD

# ifconfig fxp0 inet 192.168.50.254/24                     # 第一个 IP
# ifconfig fxp0 alias 192.168.51.254 netmask 255.255.255.0 # 第二个 IP

永久条目设置在 /etc/rc.conf 中:

ifconfig_fxp0="inet 192.168.50.254  netmask 255.255.255.0"
ifconfig_fxp0_alias0="192.168.51.254 netmask 255.255.255.0"

5.3.3. Solaris

# ifconfig hme0 plumb                                      # 启用网卡
# ifconfig hme0 192.168.50.254 netmask 255.255.255.0 up    # 第一个 IP
# ifconfig hme0:1 192.168.51.254 netmask 255.255.255.0 up  # 第二个 IP

5.4. 更改 MAC 地址

# ifconfig eth0 down
# ifconfig eth0 hw ether 00:01:02:03:04:05      # Linux
# ifconfig fxp0 link 00:01:02:03:04:05          # FreeBSD
# ifconfig hme0 ether 00:01:02:03:04:05         # Solaris
# sudo ifconfig en0 ether 00:01:02:03:04:05     # Mac OS X Tiger
# sudo ifconfig en0 lladdr 00:01:02:03:04:05    # Mac OS X Leopard

5.5. 使用中的端口

监听打开的端口:

# netstat -an | grep LISTEN
# lsof -i                                       # 列出所有因特网连接(Linux)
# socklist                                      # 列出打开的 socket (Linux)
# sockstat -4                                   # 使用 socket 的应用程序列表(FreeBSD)
# netstat -anp --udp --tcp | grep LISTEN        # Linux
# netstat -tup                                  # 列出活跃的连接(Linux)
# netstat -tupl                                 # 列出系统中正在监听的端口(Linux)
# netstat -ano                                  # Windows

5.6. 防火墙

5.6.1. Linux

# iptables -L -n -v                  # 状态信息
# iptables -P INPUT       ACCEPT     # 打开所有
# iptables -P FORWARD     ACCEPT
# iptables -P OUTPUT      ACCEPT
# iptables -Z                        # 把所有链的包及字节的计数器清空
# iptables -F                        # 清空所有链
# iptables -X                        # 删除所有链

5.6.2. FreeBSD

# ipfw show                          # 状态信息
# ipfw list 65535 # 如果显示 "65535 deny ip from any to any", 那防火墙已被禁用
# sysctl net.inet.ip.fw.enable=0     # 禁用
# sysctl net.inet.ip.fw.enable=1     # 启用

5.7. 路由 IP 转发

5.7.1. Linux

# cat /proc/sys/net/ipv4/ip_forward     # 查看 IP 转发 0=禁用, 1=启用
# echo 1 > /proc/sys/net/ipv4/ip_forward

5.7.2. FreeBSD

# sysctl net.inet.ip.forwarding          # 查看 IP 转发 0=禁用, 1=启用
# sysctl net.inet.ip.forwarding=1
# sysctl net.inet.ip.fastforwarding=1    # 专用路由器或防火墙

Permanent with entry in /etc/rc.conf:

gateway_enable="YES"                     # 如果主机是网关则设置为 YES.

5.7.3. Solaris

# ndd -set /dev/ip ip_forwarding 1       # 查看 IP 转发 0=禁用, 1=启用

5.8. NAT - 网络地址转换

5.8.1. Linux

# iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE  # 激活 NAT
# iptables -t nat -A PREROUTING -p tcp -d 78.31.70.238 --dport 20022 -j DNAT \
--to 192.168.16.44:22           # 转发端口 20022 到内部 IP 端口(ssh)
# iptables -t nat -A PREROUTING -p tcp -d 78.31.70.238 --dport 993:995 -j DNAT \
--to 192.168.16.254:993:995     # 转发 993-995 范围端口
# ip route flush cache
# iptables -L -t nat            # 查看 NAT 状态信息

5.8.2. FreeBSD

# natd -s -m -u -dynamic -f /etc/natd.conf -n fxp0

Or edit /etc/rc.conf with:

firewall_enable="YES"           # 设置 YES 来启用防火墙功能
firewall_type="open"            # 防火墙类型(看 /etc/rc.firewall)
natd_enable="YES"               # 启用 natd (如果 firewall_enable == YES).
natd_interface="tun0"           # 公共的网络接口或要使用的 IP 地址.
natd_flags="-s -m -u -dynamic -f /etc/natd.conf"

端口转发:

# cat /etc/natd.conf
same_ports yes
use_sockets yes
unregistered_only
# redirect_port tcp insideIP:2300-2399 3300-3399  # 端口范围
redirect_port udp 192.168.51.103:7777 7777

5.9. DNS

在 unix 上, 对于所有的网络接口的 DNS 条目都存储在 /etc/resolv.conf 文件中.

nameserver 78.31.70.238
search sleepyowl.net intern.lab
domain sleepyowl.net

检查系统域名:

# hostname -d                        # 等同于 dnsdomainname

5.9.1. Windows

# ipconfig /?                        # 显示帮助
# ipconfig /all                      # 显示所有信息包括 DNS
# ipconfig /flushdns                 # 清除 DNS 缓存

5.9.2. 转发查询

# dig sleepyowl.net
# dig MX google.com
# dig @127.0.0.1 NS sun.com          # 测试本地服务器
# dig @204.97.212.10 NS MX heise.de  # 查询外部
# dig AXFR @ns1.xname.org cb.vu      # 查看区传送(zone transfer)
# host -t MX cb.vu                   # 获取邮件 MX 记录
# host -t NS -T sun.com              # 通过 TCP 连接获取 NS 记录
# host -a sleepyowl.net              # 获取所有

5.9.3. 反向查询

# dig -x 78.31.70.238
# host 78.31.70.238
# nslookup 78.31.70.238

5.9.4. /etc/hosts

单个主机可以配置于文件 /etc/hosts 来代替本地正在运行的 named 反向域名查询.

78.31.70.238   sleepyowl.net   sleepyowl

5.10. DHCP

5.10.1. Linux

# dhcpcd -n eth0           # 触发更新(并不总是可以工作)
# dhcpcd -k eth0           # 释放并关闭

租约(lease)的全部信息存储在: /var/lib/dhcpcd/dhcpcd-eth0.info

5.10.2. FreeBSD

# dhclient bge0

租约(lease)的全部信息存储在: /var/db/dhclient.leases.bge0 /etc/dhclient.conf:

# cat /etc/dhclient.conf
interface "rl0" {
    prepend domain-name-servers 127.0.0.1;
    default domain-name "sleepyowl.net";
    supersede domain-name "sleepyowl.net";
}

5.10.3. Windows

# ipconfig /renew          # 更新所有适配器
# ipconfig /renew LAN      # 更新名叫 "LAN" 的适配器
# ipconfig /release WLAN   # 释放名叫 "WLAN" 的适配器

5.11. 通信量分析(Traffic analysis)

5.11.1. 用 tcpdump 嗅探(sniff)

# tcpdump -nl -i bge0 not port ssh and src \(192.168.16.121 or 192.168.16.54\)
# tcpdump -l > dump && tail -f dump               # 缓冲输出
# tcpdump -i rl0 -w traffic.rl0                   # 把数据报文写入二进制文件
# tcpdump -r traffic.rl0                          # 从文件读取数据报文(也可以使用 ethereal)
# tcpdump port 80                                 # 两个经典命令
# tcpdump host google.com
# tcpdump -i eth0 -X port \(110 or 143\)          # 查看端口 110(POP) 或 143(IMAP)的数据报文
# tcpdump -n -i eth0 icmp                         # 只捕获 ping
# tcpdump -i eth0 -s 0 -A port 80 | grep GET      # -s 0 为全部包, -A 为 ASCII

5.11.2. 用 nmap 扫描

# nmap cb.vu               # 扫描主机上所有保留的 TCP 端口
# nmap -sP 192.168.16.0/24 # 找出在 0/24 上主机所使用的 IP
# nmap -sS -sV -O cb.vu    # 做秘密 SYN 扫描来探测系统和系统服务的版本信息

5.12. 流量控制(QoS)

5.12.1. 上传限制

  1. Linux
    # tc qdisc add dev eth0 root tbf rate 480kbit latency 50ms burst 1540
    # tc -s qdisc ls dev eth0                         # 状态
    # tc qdisc del dev eth0 root                      # 删除队列
    # tc qdisc change dev eth0 root tbf rate 220kbit latency 50ms burst 1540
    
  2. FreeBSD
    # kldload dummynet                                # 如有必要加载这个模块
    # ipfw pipe 1 config bw 500Kbit/s                 # 创建一个带宽限制的 pipe
    # ipfw add pipe 1 ip from me to any               # 转移所有上传进入这个 pipe
    

5.12.2. 服务质量 (Quality of service)

  1. Linux
    # tc qdisc add dev eth0 root handle 1: prio priomap 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 0
    # tc qdisc add dev eth0 parent 1:1 handle 10: sfq
    # tc qdisc add dev eth0 parent 1:2 handle 20: sfq
    # tc qdisc add dev eth0 parent 1:3 handle 30: sfq
    # tc filter add dev eth0 protocol ip parent 1: prio 1 u32 \
      match ip dport 10000 0x3C00 flowid 1:1          # 使用服务端端口范围
      match ip dst 123.23.0.1 flowid 1:1              # 或/和使用服务器 IP
    
  2. FreeBSD
    # ipfw pipe 1 config bw 500Kbit/s
    # ipfw queue 1 config pipe 1 weight 100
    # ipfw queue 2 config pipe 1 weight 10
    # ipfw queue 3 config pipe 1 weight 1
    # ipfw add 10 queue 1 proto udp dst-port 10000-11024
    # ipfw add 11 queue 1 proto udp dst-ip 123.23.0.1 # 或/和使用服务器 IP
    # ipfw add 20 queue 2 dsp-port ssh
    # ipfw add 30 queue 3 from me to any              # 剩余所有
    

5.13. NIS 调试

# ypwhich                  # 获取提供 NIS 服务的服务器名
# domainname               # 已配置的 NIS 域名
# ypcat group              # 列印 NIS 映射 group
# cd /var/yp && make       # 重建 yp 数据库
# ps auxww | grep ypbind
# yppoll passwd.byname
# cat /etc/yp.conf

6. SSH SCP

6.1. Public key authentication

# ssh-keygen -t dsa -N ''
# cat ~/.ssh/id_dsa.pub | ssh you@host-server "cat - >> ~/.ssh/authorized_keys2"

6.1.1. 使用来自 ssh.com 的 Windows 客户端

# cd ~/.ssh
# ssh-keygen -i -f keyfilename.pub >> authorized_keys2

6.1.2. 在 Windows 上使用 Putty

# scp .ssh/puttykey.pub root@192.168.51.254:.ssh/
# cd ~/.ssh
# ssh-keygen -i -f puttykey.pub >> authorized_keys2

6.2. 检查指纹

# ssh-keygen -l -f /etc/ssh/ssh_host_rsa_key.pub      # RSA 密钥
# ssh-keygen -l -f /etc/ssh/ssh_host_dsa_key.pub      # DSA 密钥(默认)
# ssh linda

6.3. 安全文件传输

# scp file.txt host-two:/tmp
# scp joe@host-two:/www/*.html /www/tmp
# scp -r joe@host-two:/www /www/tmp

在 Konqueror 或 Midnight 控制台中, 用地址 fish://user@gate 来访问远程文件系统是可行的, 就是比较慢而已.

6.4. 隧道(Tunneling)

# ssh -L localport:desthost:destport user@gate  # gate 为目标主机网关
# ssh -R destport:desthost:localport user@gate  # 转发你的 localport 到目标端口
# ssh -X user@gate   # 转发 X 程序

6.4.1. 在 gate 上直接转发

# ssh -L 2401:localhost:2401 -L 8080:localhost:80 user@gate

6.4.2. 转发 Netbios 和远程桌面到第二个服务器

# ssh -L 139:smbserver:139 -L 3388:smbserver:3389 user@gate

6.4.3. 在 NAT 后面连接两个客户端

开启 cliuser 客户端(从目标到 gate):

# ssh -R 2022:localhost:22 user@gate            # 转发客户端 22 端口到 gate:2022 端口

开启 cliadmin 客户端(从主机到 gate):

# ssh -L 3022:localhost:2022 admin@gate         # 转发客户端 3022 端口到 gate:2022 端口

现在 admin 可以直接连接 cliuser 客户端:

# ssh -p 3022 admin@localhost                   # local:3022 -> gate:2022 -> client:22

6.4.4. 在 NAT 后面的 VNC 连接

开启 cliwin 客户端到 gate:

# ssh -R 15900:localhost:5900 user@gate

开启 cliadmin 客户端(从主机到 gate):

# ssh -L 5900:localhost:15900 admin@gate

现在 admin 直接连接到 VNC 客户端:

# vncconnect -display :0 localhost

7. 使用 SSH 建立 VPN

7.1. 单个 P2P 连接

7.1.1. 连接到服务端

Linux上的服务端:

cli># ssh -w5:5 root@hserver
srv># ifconfig tun5 10.0.1.1 netmask 255.255.255.252   # 在服务端 shell 上执行

FreeBSD上的服务端:

cli># ssh -w5:5 root@hserver
srv># ifconfig tun5 10.0.1.1 10.0.1.2                  # 在服务端 shell 上执行

7.1.2. 连接到客户端

cli># ifconfig tun5 10.0.1.2 netmask 255.255.255.252   # Linux上的客户端
cli># ifconfig tun5 10.0.1.2 10.0.1.1                  # FreeBSD上的客户端

7.2. 连接两个网络

7.2.1. 连接 gateA 到 gateB

Linux 上的 gateB:

gateA># ssh -w5:5 root@gateB
gateB># ifconfig tun5 10.0.1.1 netmask 255.255.255.252 # 在 gateB 的 shell 中执行
gateB># route add -net 192.168.51.0 netmask 255.255.255.0 dev tun5
gateB># echo 1 > /proc/sys/net/ipv4/ip_forward         # 如果不是默认网关
gateB># iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

FreeBSD 上的 gateB:

gateA># ssh -w5:5 root@gateB                          # 创建 tun5 设备
gateB># ifconfig tun5 10.0.1.1 10.0.1.2               # 在 gateB 的 shell 中执行
gateB># route add 192.168.51.0/24 10.0.1.2
gateB># sysctl net.inet.ip.forwarding=1               # 如果不是默认网关
gateB># natd -s -m -u -dynamic -n fxp0                # 看 NAT
gateA># sysctl net.inet.ip.fw.enable=1

7.2.2. 配置 gateA

Linux 上的 gateA:

gateA># ifconfig tun5 10.0.1.2 netmask 255.255.255.252
gateA># route add -net 192.168.16.0 netmask 255.255.255.0 dev tun5
gateA># echo 1 > /proc/sys/net/ipv4/ip_forward
gateA># iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

FreeBSD 上的 gateA:

gateA># ifconfig tun5 10.0.1.2 10.0.1.1
gateA># route add 192.168.16.0/24 10.0.1.2
gateA># sysctl net.inet.ip.forwarding=1
gateA># natd -s -m -u -dynamic -n fxp0                # 看 NAT
gateA># sysctl net.inet.ip.fw.enable=1

8. RSYNC

# rsync -a /home/colin/ /backup/colin/
# rsync -a /var/ /var_bak/
# rsync -aR --delete-during /home/user/ /backup/      # 使用相对路径(看下面)
# rsync -axSRzv /home/user/ user@server:/backup/user/
# rsync -azR --exclude /tmp/ /home/user/ user@server:/backup/
# rsync -az -e 'ssh -p 20022' /home/colin/ user@server:/backup/colin/
# rsync -axSRz /home/ ruser@hostname::rmodule/backup/
# rsync -axSRz ruser@hostname::rmodule/backup/ /home/    # 回拷贝

一些重要选项:

-a, --archive
归档模式, 等于 -rlptgoD (非 -H)
-r, --recursive
对子目录以递归模式处理
-R, --relative
使用相对路径名
-H, --hard-links
保留硬链结
-S, --sparse
对稀疏文件进行特殊处理以节省DST的空间
-x, --one-file-system
不跨越文件系统边界
--exclude=PATTERN
指定排除不需要传输的文件模式
--delete-during
传输期间删除
--delete-after
传输结束以后再删除

8.1. 在 Windows 上使用 Rsync

8.1.1. 公钥认证

# ssh-keygen -t dsa -N ''                   # 创建密钥对
# rsync user@server:.ssh/authorized_keys2 . # 从服务器拷贝本地文件
# cat id_dsa.pub >> authorized_keys2        # 或者使用编辑器添加这个公钥
# rsync authorized_keys2 user@server:.ssh/  # 拷贝文件回服务器
# del authorized_keys2                      # 删除本地拷贝

现在测试一下(在同一行里面):

rsync -rv "/cygdrive/c/Documents and Settings/%USERNAME%/My Documents/" \
'user@server:My\ Documents/'

8.1.2. 自动备份

创建批处理文件 backup.bat

@ECHO OFF
REM rsync the directory My Documents
SETLOCAL
SET CWRSYNCHOME=C:\PROGRAM FILES\CWRSYNC
SET CYGWIN=nontsec
SET CWOLDPATH=%PATH%
REM uncomment the next line when using cygwin
SET PATH=%CWRSYNCHOME%\BIN;%PATH%
echo Press Control-C to abort
rsync -av "/cygdrive/c/Documents and Settings/%USERNAME%/My Documents/" \
'user@server:My\ Documents/'
pause

9. SUDO

# sudo /etc/init.d/dhcpd restart            # 用 root 权限运行 rc 脚本
# sudo -u sysadmin whoami                   # 使用其他用户运行命令

9.1. 配置

Sudo 的配置在 /etc/sudoers 中, 并且只能用 visudo 编辑. 下面是 sudoers 例子:

# cat /etc/sudoers
# 主机别名
Host_Alias   DMZ     = 212.118.81.40/28
Host_Alias   DESKTOP = work1, work2

# 用户别名 和 runas 别名
User_Alias   ADMINS  = colin, luca, admin
User_Alias   DEVEL   = joe, jack, julia
Runas_Alias  DBA     = oracle,pgsql

# 命令别名, 其值为全路径命令
Cmnd_Alias   SYSTEM  = /sbin/reboot,/usr/bin/kill,/sbin/halt,/sbin/shutdown,/etc/init.d/
Cmnd_Alias   PW      = /usr/bin/passwd [A-z]*, !/usr/bin/passwd root # Not root pwd!
Cmnd_Alias   DEBUG   = /usr/sbin/tcpdump,/usr/bin/wireshark,/usr/bin/nmap
# 一个真实的规则
root,ADMINS  ALL     = (ALL) NOPASSWD: ALL    # ADMINS 别名中的用户可做任何事情不需要密码
DEVEL        DESKTOP = (ALL) NOPASSWD: ALL    # 开发人员可在 DESKTOP 别名的主机上做任何事情
DEVEL        DMZ     = (ALL) NOPASSWD: DEBUG  # 开发人员可以在 DMZ 别名的主机上使用 DEBUG 别名中的命令

# 用户 sysadmin 可以在 DMZ 服务器上执行一些命令
sysadmin     DMZ     = (ALL) NOPASSWD: SYSTEM,PW,DEBUG
sysadmin     ALL,!DMZ = (ALL) NOPASSWD: ALL   # 可以在非 DMZ 主机上做任何事情
%dba         ALL     = (DBA) ALL              # 用户组 dba 可以运行 DBA 别名中用户权限的所有命令

# 所有用户可以在 DESKTOP 别名的主机上 挂载/卸载 CD-ROM
ALL          DESKTOP = NOPASSWD: /sbin/mount /cdrom,/sbin/umount /cdrom

10. 文件加密

10.1. 单个文件

加密和解密:

# openssl des -salt -in file -out file.des
# openssl des -d -salt -in file.des -out file

10.2. 归档并加密整个目录

# tar -cf - directory | openssl des -salt -out directory.tar.des      # 加密
# openssl des -d -salt -in directory.tar.des | tar -x                 # 解密

10.3. 压缩归档并加密整个目录

# tar -zcf - directory | openssl des -salt -out directory.tar.gz.des  # 加密
# openssl des -d -salt -in directory.tar.gz.des | tar -xz             # 解密

10.4. GPG

# gpg -c file                        # 使用密码加密文件
# gpg file.gpg                       # 文件解密(选项 -o 其他文件)

10.4.1. 使用密钥

# gpg --gen-key                      # 这需要一些时间

常用选项的简短描述:

-e
加密数据
-d
解密数据
-r
为某个收件者加密('全名' 或者 'email@domain')
-a
输出经过 ascii 封装的密钥
-o
指定输出文件
  1. 只用于个人的加密
    # gpg -e -r 'Your Name' file                  # 使用你的公钥加密
    # gpg -o file -d file.gpg                     # 解密. 使用 -o 指定输出文件
    
  2. 用密钥加密-解密
    # gpg -a -o alicekey.asc --export 'Alice'               # Alice 导出她的公钥到 ascii 文件中
    # gpg --send-keys --keyserver subkeys.pgp.net KEYID     # Alice 把她的公钥放入一个服务器
    # gpg --import alicekey.asc                             # 你导入她的密钥到你的公钥环(pubring)中
    # gpg --search-keys --keyserver subkeys.pgp.net 'Alice' # 或者从一个服务器中获取他的公钥
    # gpg -e -r 'Alice' file                      # 给 Alice 加密文件
    # gpg -d file.gpg -o file                     # 解密 Alice 给你的加密文件
    
  3. 密钥管理
    # gpg --list-keys                             # 列出所有公钥并查看其 KEYID
    # gpg --gen-revoke 'Your Name'                # 产生一份撤销密钥证书
    # gpg --list-secret-keys                      # 列出所有私钥
    # gpg --delete-keys NAME                      # 从本的密钥环中删除一个公钥
    # gpg --delete-secret-key NAME                # 从本的密钥环中删除一个私钥
    # gpg --fingerprint KEYID                     # 显示 KIYID 这个密钥的指纹
    # gpg --edit-key KEYID                        # 编辑密钥(比如签名或者添加/删除 email)
    

11. 分区加密

11.1. Linux

11.1.1. dm-crypt with LUKS

  1. 创建加密分区
    # dd if=/dev/urandom of=/dev/sdc1          # 可选
    # cryptsetup -y luksFormat /dev/sdc1       # 这破坏了在 sdc1 上的数据
    # cryptsetup luksOpen /dev/sdc1 sdc1
    # mkfs.ext3 /dev/mapper/sdc1               # 创建 ext3 文件系统
    # mount -t ext3 /dev/mapper/sdc1 /mnt
    # umount /mnt
    # cryptsetup luksClose sdc1                # Detach 已加密的分区
    
  2. Attach
    # cryptsetup luksOpen /dev/sdc1 sdc1
    # mount -t ext3 /dev/mapper/sdc1 /mnt
    
  3. Detach
    # umount /mnt
    # cryptsetup luksClose sdc1
    

11.1.2. dm-crypt without LUKS

# cryptsetup -y create sdc1 /dev/sdc1      # 或任何其他分区像 /dev/loop0
# dmsetup ls                               # 检查一下, 将显示: sdc1 (254, 0)
# mkfs.ext3 /dev/mapper/sdc1               # 只有第一次要这么做!
# mount -t ext3 /dev/mapper/sdc1 /mnt
# umount /mnt/
# cryptsetup remove sdc1                   # Detach 已加密的分区

11.2. FreeBSD

11.2.1. 使用密码和密钥

  1. 创建加密分区
    # dd if=/dev/random of=/root/ad1.key bs=64 count=1  # 加密主密钥的密钥
    # geli init -s 4096 -K /root/ad1.key /dev/ad1       # 对于磁盘也可用 -s 8192
    # geli attach -k /root/ad1.key /dev/ad1             # 将 /dev/ad1 与所生成的密钥 /root/ad1.key 关联
    # dd if=/dev/random of=/dev/ad1.eli bs=1m           # 可选, 需要很长时间
    # newfs /dev/ad1.eli                                # 创建文件系统
    # mount /dev/ad1.eli /mnt
    
  2. Attach
    # geli attach -k /root/ad1.key /dev/ad1
    # fsck -ny -t ffs /dev/ad1.eli                      # 检查文件系统
    # mount /dev/ad1.eli /mnt
    
  3. Detach
    # umount /mnt
    # geli detach /dev/ad1.eli
    

11.2.2. 仅用密码

# dd if=/dev/zero of=/cryptedfile bs=1M count=1000  # 1 GB 文件
# mdconfig -at vnode -f /cryptedfile
# geli init /dev/md0                                # 仅用密码加密
# geli attach /dev/md0
# newfs -U -m 0 /dev/md0.eli
# mount /dev/md0.eli /mnt
# umount /dev/md0.eli
# geli detach md0.eli

现在可以把这个映像文件加载成仅需密码的文件系统.

# mdconfig -at vnode -f /cryptedfile
# geli attach /dev/md0
# mount /dev/md0.eli /mnt

12. SSL 认证

12.1. 步骤

  1. 我们需要一个证书颁发机构来签署我们的证书.
  2. 创建一个证书签发申请(signing request).
  3. 证书颁发机构签署证书.
  4. 如果有需要, 加入证书和密钥到单个文件来给应用程序使用.

12.2. 配置 OpenSSL

确保所有目录已经创建:

# mkdir -p /usr/local/certs/CA
# cd /usr/local/certs/CA
# mkdir certs crl newcerts private
# echo "01" > serial                        # 仅当 serial 不存在时
# touch index.txt

12.3. 创建一个认证授权

# openssl req -new -x509 -days 730 -config /etc/ssl/openssl.cnf \
-keyout CA/private/cakey.pem -out CA/cacert.pem

12.4. 创建证书签发申请

# openssl req -new -keyout newkey.pem -out newreq.pem \
-config /etc/ssl/openssl.cnf
# openssl req -nodes -new -keyout newkey.pem -out newreq.pem \
-config /etc/ssl/openssl.cnf                # 不对这个密钥加密

12.5. 签署证书

# cat newreq.pem newkey.pem > new.pem
# openssl ca -policy policy_anything -out servernamecert.pem \
-config /etc/ssl/openssl.cnf -infiles new.pem
# mv newkey.pem servernamekey.pem

12.6. 创建联合认证(united certificate)

最后 servername.pem 文件应该看起来像这样:

-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDutWy+o/XZ/[...]qK5LqQgT3c9dU6fcR+WuSs6aejdEDDqBRQ
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIERzCCA7CgAwIBAgIBBDANB[...]iG9w0BAQQFADCBxTELMAkGA1UEBhMCREUx
-----END CERTIFICATE-----

12.7. 查看证书信息

# openssl x509 -text -in servernamecert.pem      # 显示证书信息
# openssl req -noout -text -in server.csr        # 显示申请信息
# openssl s_client -connect cb.vu:443            # 检查 web 服务器认证信息

13. CVS

13.1. 服务器设置

13.1.1. CVS 环境初始化

# mkdir -p /usr/local/cvs
# setenv CVSROOT /usr/local/cvs      # 设置 CVSROOT 环境变量(本地)
# cvs init                           # 创建所有初始化 CVS 配置文件
# cd /root
# cvs checkout CVSROOT               # 签出配置文件来修改他们
# cd CVSROOT
# cvs commit config
# cvs add writers                    # 添加文件 writers 进 repository
# cvs edit checkoutlist
# cvs commit                         # 提交所有配置更改

13.1.2. 用 inetd 设置网络

/etc/inetd.conf 中配置如下行:

cvspserver      stream  tcp  nowait  cvs  /usr/bin/cvs  cvs \
--allow-root=/usr/local/cvs pserver

13.1.3. 单独认证

# htpasswd -cb passwd user1 password1  # -c 创建文件
# htpasswd -b passwd user2 password2

它看起来像这样:

# cat passwd
user1:xsFjhU22u8Fuo:cvs
user2:vnefJOsnnvToM:cvs

13.2. 测试它

# cvs -d :pserver:colin@192.168.50.254:/usr/local/cvs login

13.3. CVSROOT 变量

# setenv CVSROOT :pserver:<username>@<host>:/cvsdirectory
# setenv CVSROOT /usr/local/cvs                               # 仅限本的使用
# setenv CVSROOT :local:/usr/local/cvs                        # 同上
# setenv CVSROOT :ext:user@cvsserver:/usr/local/cvs           # 通过 SSH 直接访问
# setenv CVS_RSH ssh                                          # ext 协议访问
# setenv CVSROOT :pserver:user@cvsserver.254:/usr/local/cvs   # 通过 pserver 网络访问

13.4. 通过 SSH 隧道访问 CVS

在 shell 1:

# ssh -L2401:localhost:2401 colin@cvs_server
# ssh -L2401:cvs_server:2401 colin@gateway

在 shell 2:

# setenv CVSROOT :pserver:colin@localhost:/usr/local/cvs
# cvs login
# cvs checkout MyProject/src

13.5. CVS 命令及其使用

13.5.1. 导入

# cvs import [options] directory-name vendor-tag release-tag
# cd /devel
# cvs import myapp Company R1_0

13.5.2. 签出, 更新和提交

# cvs co myapp/tools                 # 仅会签出 tools 目录
# cvs co -r R1_1 myapp               # 签出修订版本为 R1_1 的 myapp (sticky)
# cvs -q -d update -P                # 典型的 CVS 更新
# cvs update -A                      # 重置所有 sticky 标签(或日期, 选项)
# cvs add newfile                    # 添加一个新文件
# cvs add -kb newfile                # 添加一个二进制文件
# cvs commit file1 file2             # 仅提交这两个文件
# cvs commit -m "message"            # 提交所有更改并为这个更改添加日志消息

13.5.3. 创建一个 patch

# cd /devel/project
# diff -Naur olddir newdir > patchfile
# diff -Naur oldfile newfile > patchfile

13.5.4. 应用一个 patch

# cd /devel/project
# patch --dry-run -p0 < patchfile    # Test the path without applying it
# patch -p0 < patchfile
# patch -p1 < patchfile              # strip off the 1st level from the path

14. SVN

14.1. Server setup

# svnadmin create --fs-type fsfs /home/svn/project1

访问方式:

file://
Direct file system access
svn:// or svn+ssh://
Remote access with the svnserve server
http://
Remote access with webdav using apache.
# svn import /project1/ file:///home/svn/project1/trunk -m 'Initial import'
# svn checkout file:///home/svn/project1

14.2. Remote access with ssh

# svn checkout svn+ssh://hostname/home/svn/project1
# groupadd subversion
# groupmod -A user1 subversion
# chown -R root:subversion /home/svn
# chmod -R 770 /home/svn

14.3. Remote access with http (apache)

Apache 配置:

LoadModule dav_module         modules/mod_dav.so
LoadModule dav_svn_module     modules/mod_dav_svn.so
LoadModule authz_svn_module   modules/mod_authz_svn.so
<Location /svn>
  DAV svn
  SVNParentPath /home/svn
  AuthType Basic
  AuthName "Subversion repository"
  AuthzSVNAccessFile /etc/apache2/svn.acl
  AuthUserFile /etc/apache2/svn-passwd
  Require valid-user
</Location>
# chown -R www:www /home/svn
# htpasswd -c /etc/svn-passwd user1

Access control svn.acl example:

[/]
 * = r
[groups]
project1-developers = joe, jack, jane
[project1:]
@project1-developers = rw

14.4. SVN commands and usage

14.4.1. Import

# svn help import
# svn import /project1/newdir http://host.url/svn/project1/trunk/src -m 'add newdir'

14.4.2. Typical SVN commands

# svn co http://host.url/svn/project1/trunk
# svn mkdir http://host.url/svn/project1/tags/
# svn copy -m "Tag rc1 rel." http://host.url/svn/project1/trunk \
                             http://host.url/svn/project1/tags/1.0rc1
# svn status [--verbose]
# svn add src/file.h src/file.cpp
# svn commit -m 'Added new class file'
# svn ls http://host.url/svn/project1/tags/
# svn move foo.c bar.c
# svn delete some_old_file

15. 实用命令

15.1. less

# less unixtoolbox.xhtml
h, H
显示指令的汇总列表
f, ^F, ^V, SPACE
向前滚动一屏
b, ^B, ESC-v
向后滚动一屏
F
向前滚动; 类似于"tail -f"
/
pattern 向前搜索
?
pattern 向后搜索
n
重复之前的搜索
N
反方向重复之前的搜索
q
退出

15.2. vi

15.2.1. Quit

:w newfilename
保存文件为 newfilename
:wq or :x
保存并退出
:q!
退出但不保存

15.2.2. 移动和查找

/
string 向前查找 string
?
string 向后查找 string
n
同方向重复上一次搜索命令
N
反方向重复上一次搜索命令
{
光标移至段落结尾
}
光标移至段落开头
1G
光标移至文件的第一行首
nG
光标移至文件的第 n 行首
G
光标移至文件的最后一行首
:%s/OLD/NEW/g
替换所有查找到的 OLD 为 NEW

15.2.3. 删除文本

dd
删除当前行
D
删除光标到当前行末尾的字符
dw
删除单词
x
删除字符
u
回复上一次操作
U
回复所有此行的更改

15.3. mail

# mail c@cb.vu
Subject: Your text is full of typos
"For a moment, nothing happened. Then, after a second or so,
nothing continued to happen."
.
EOT
#
# echo "This is the mail body" | mail c@cb.vu

15.4. tar

15.4.1. 创建

# cd /
# tar -cf home.tar home/        # 归档整个 /home 目录(c 为创建)
# tar -czf home.tgz home/       # 等同于 zip 压缩
# tar -cjf home.tbz home/       # 等同于 bzip2 压缩
# tar -C /usr -czf local.tgz local/etc local/www
# tar -C /usr -xzf local.tgz    # 释放 local 目录到 /usr
# cd /usr; tar -xzf local.tgz   # 同上面一样

15.4.2. 释放(Extract)

# tar -tzf home.tgz             # 列出归档文件中的所有文件, 并不释放
# tar -xf home.tar              # 释放归档文件(x 为释放)
# tar -xzf home.tgz             # 等同于 zip 压缩
# tar -xjf home.tgz             # 等同于 bzip2 压缩
# tar -xjf home.tgz home/colin/file.txt    # 释放单个文件

15.4.3. 更高级的

# tar c dir/ | gzip | ssh user@remote 'dd of=dir.tgz' # 归档压缩 dir/ 目录并存储到远程主机上
# tar cvf - `find . -print` > backup.tar              # 归档当前目录
# tar -cf - -C /etc . | tar xpf - -C /backup/etc      # 拷贝目录
# tar -cf - -C /etc . | ssh user@remote tar xpf - -C /backup/etc      # 远程拷贝
# tar -czf home.tgz --exclude '*.o' --exclude 'tmp/' home/

15.5. dd

15.5.1. 备份和恢复

# dd if=/dev/hda of=/dev/hdc bs=16065b                # 拷贝磁盘到磁盘(相同大小)
# dd if=/dev/sda7 of /home/root.img bs=4096 conv=notrunc,noerror # 备份 /
# dd if /home/root.img of=/dev/sda7 bs=4096 conv=notrunc,noerror # 恢复 /
# dd bs=1M if=/dev/ad4s3e | gzip -c > ad4s3e.gz                  # 压缩备份
# gunzip -dc ad4s3e.gz | dd of=/dev/ad0s3e bs=1M                 # 解压恢复
# dd bs=1M if=/dev/ad4s3e | gzip | ssh eedcoba@fry 'dd of=ad4s3e.gz' # 也可为远程的
# gunzip -dc ad4s3e.gz | ssh eedcoba@host 'dd of=/dev/ad0s3e bs=1M'
# dd if=/dev/ad0 of=/dev/ad2 skip=1 seek=1 bs=4k conv=noerror    # 忽略 MBR

15.5.2. 恢复

# dd if=/dev/hda of=/dev/null bs=1m                   # 检查坏扇区
# dd bs=1k if=/dev/hda1 conv=sync,noerror,notrunc | gzip | ssh \ # 发送到远程
root@fry 'dd of=hda1.gz bs=1k'
# dd bs=1k if=/dev/hda1 conv=sync,noerror,notrunc of=hda1.img    # 存储为一个映像文件
# mount -o loop /hda1.img /mnt                        # 挂载这个映像文件
# rsync -ax /mnt/ /newdisk/                           # 拷贝到一个新磁盘
# dd if=/dev/hda of=/dev/hda                          # 刷新磁状态

15.5.3. 删除

# dd if=/dev/zero of=/dev/hdc                         # 删除全部数据
# dd if=/dev/urandom of=/dev/hdc                      # 更好的删除全部数据
# kill -USR1 PID                                      # 查看 dd 进度(仅Linux!)

15.5.4. MBR 技巧

# dd if=/dev/sda of=/mbr_sda.bak bs=512 count=1                  # 完全备份 MBR
# dd if=/dev/zero of=/dev/sda bs=512 count=1                     # 删除 MBR 和分区表
# dd if=/mbr_sda.bak of=/dev/sda bs=512 count=1                  # 完全恢复MBR
# dd if=/mbr_sda.bak of=/dev/sda bs=446 count=1                  # 仅回复引导程序
# dd if=/mbr_sda.bak of=/dev/sda bs=1 count=64 skip=446 seek=446 # 恢复分区表

15.6. screen

15.6.1. 简短实例

# screen
# top

现在用 Ctrl-a Ctrl-d 来 detach. Reattach 终端:

# screen -r
# screen -R -D

15.6.2. Screen 命令 (在 screen 中)

Ctrl-a ?
各功能的帮助摘要
Ctrl-a c
创建一个新的 window (终端)
Ctrl-a Ctrl-nCtrl-a Ctrl-p
切换到下一个或前一个 window
Ctrl-a Ctrl-N
N 为 0 到 9 的数字, 用来切换到相对应的 window
Ctrl-a "
获取所有正在运行的 window 的可导航的列表
Ctrl-a a
清楚错误的 Ctrl-a
Ctrl-a Ctrl-d
断开所有会话, 会话中所有任务运行于后台
Ctrl-a x
用密码锁柱 screen 终端

15.7. Find

# find . -type f ! -perm -444        # 寻找所有无法读取的文件
# find . -type d ! -perm -111        # 寻找所有无法访问的目录
# find /home/user/ -cmin 10 -print   # 寻找最后 10 分钟创建或修改的文件
# find . -name '*.[ch]' | xargs grep -E 'expr' # 在当前目录及子目录搜索 'expr' 表达式
# find / -name "*.core" | xargs rm   # 寻找 core 垃圾并删除它们(也可试试 core.*)
# find / -name "*.core" -print -exec rm {} \;  # 另一种语法
# find . \( -iname "*.png" -o -iname "*.jpg" \) -print -exec tar -rf images.tar {} \;
# find . -type f -name "*.txt" ! -name README.txt -print  # 除 README.txt 的文件
# find /var/ -size +10M -exec ls -lh {} \;     # 查找 > 10 MB 的文件
# find /var/ -size +10M -ls           # 这个更简单
# find . -size +10M -size -50M -print
# find /usr/ports/ -name work -type d -print -exec rm -rf {} \;  # 清理 port
# find / -type f -user root -perm -4000 -exec ls -l {} \;
# find . -type f | xargs ls -l       # 不能工作于有空格的名字
# find . -type f -print0 | xargs -0 ls -l  # 可工作于有空格的名字
# find . -type f -exec ls -l '{}' \; # 或使用用于 -exec 的引用 '{}'

15.8. 混杂的

# which command                      # 显示命令的全路径名
# time command                       # 显示一个命令执行完成所用的时间
# time cat                           # 使用 time 作为秒表, 用 Ctrl-c 来停止
# set | grep $USER                   # 列显当前环境变量
# cal -3                             # 显示三个月日历
# date [-u|--utc|--universal] [MMDDhhmm[[CC]YY][.ss]]
# date 10022155                      # 设置日期和时间
# whatis grep                        # 显示命令的简短信息
# whereis java                       # 查询命令的的路径和标准目录
# setenv varname value               # 设置环境变量, 设置变量 varname 的值为 value (csh/tcsh)
# export varname="value"             # 设置环境变量, 设置变量 varname 的值为 value  (sh/ksh/bash)
# pwd                                # 显示当前工作目录
# mkdir -p /path/to/dir              # 如果存在不显示错误, 建立所需的上级目录
# mkdir -p project/{bin,src,obj,doc/{html,man,pdf},debug/some/more/dirs}
# rmdir /path/to/dir                 # 移除目录
# rm -rf /path/to/dir                # 移除目录和其内容(强制)
# cp -la /dir1 /dir2                 # 存档, 硬连接目录所有文件, 用来替代拷贝
# cp -lpR /dir1 /dir2                # 同上 (FreeBSD)
# cp unixtoolbox.xhtml{,.bak}        # 拷贝文件成新扩展名的快速方法
# mv /dir1 /dir2                     # 修改目录名

16. 软件安装

16.1. 列出已安装过的软件包

# rpm -qa                            # 列出已安装过的软件包(RH, SuSE, 基于 RPM 的)
# dpkg -l                            # Debian, Ubuntu
# pkg_info                           # 列出所有已安装过的软件包(FreeBSD)
# pkg_info -W smbd                   # 查看 smbd 安装了那些软件包(FreeBSD)
# pkginfo                            # Solaris

16.2. 添加/删除软件

# rpm -i pkgname.rpm                 # 安装软件包(RH, SuSE, 基于 RPM 的)
# rpm -e pkgname                     # 删除软件包

16.2.1. Debian

# apt-get update                     # 更新源列表
# apt-get install emacs              # 安装 emacs 软件包
# dpkg --remove emacs                # 删除 emacs 软件包
# dpkg -S file                       # 查找拥有该 file 的软件包

16.2.2. Gentoo

# emerge --sync                      # 同步更新本地 protage 树
# emerge -u packagename              # 安装或更新一个软件包
# emerge -C packagename              # 删除软件包
# revdep-rebuild                     # 修复依赖关系的缺失

16.2.3. Solaris

# pkgadd -d <cdrom>/Solaris_9/Product SUNWgtar
# pkgadd -d SUNWgtar                 # 添加下载的软件包(先要 bunzip2)
# pkgrm SUNWgtar                     # 删除软件包

16.2.4. FreeBSD

# pkg_add -r rsync                   # 获取并安装 rsync
# pkg_delete /var/db/pkg/rsync-xx    # 删除 rsync 软件包

16.2.5. FreeBSD ports

# portsnap fetch extract             # 当第一次运行这个命令, 会创建 port 树
# portsnap fetch update              # 跟新 port 树
# cd /usr/ports/net/rsync/           # 选择软件安装目录
# make install distclean             # 安装并清理(也可看 man ports)
# make package                       # Make 一个二进制软件包

16.2.6. 库路径

# ldd /usr/bin/rsync                 # 列出所有所需的运行时库
# ldconfig -n /path/to/libs/         # 添加一个路径到共享库目录Add a path to the shared libraries directories
# ldconfig -m /path/to/libs/         # FreeBSD

17. 媒体转换

17.1. 文本编码

# iconv -f <from_encoding> -t <to_encoding> <input_file>
# iconv -f ISO8859-1 -t UTF-8 -o file.input > file_utf8
# iconv -l                           # 列显系统所支持的字符编码

17.2. Unix - DOS 新行

# sed 's/.$//' dosfile.txt > unixfile.txt
# sed -n p unixfile.txt > dosfile.txt

17.3. PDF 转换成 Jpeg 和 连接一串 PDF 文件

# gs -dBATCH -dNOPAUSE -sDEVICE=jpeg -r150 -dTextAlphaBits=4 -dGraphicsAlphaBits=4 \
 -dMaxStripSize=8192 -sOutputFile=unixtoolbox_%d.jpg unixtoolbox.pdf
# convert unixtoolbox.pdf unixtoolbox-%03d.png
# convert *.jpeg images.pdf          # 把所有图片转换成一份简单的 PDF 文档
# gs -q -sPAPERSIZE=a4 -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=all.pdf \
file1.pdf file2.pdf ...              # 在 Windows 上使用 '#' 代替 '='

17.4. 视频转换

# mencoder -o videoout.avi -oac mp3lame -ovc lavc -srate 11025 \
-channels 1 -af-adv force=1 -lameopts preset=medium -lavcopts \
vcodec=msmpeg4v2:vbitrate=600 -mc 0 vidoein.AVI

17.5. 拷贝音频光盘

# cdparanoia -B                      # 拷贝音轨成 wav 文件到当前目录列表(dir)
# lame -b 256 in.wav out.mp3         # 编码成 256 kb/s 的 mp3
# for i in *.wav; do lame -b 256 $i `basename $i .wav`.mp3; done
# oggenc in.wav -b 256 out.ogg       # 编码成 256 kb/s 的 Ogg Vorbis

18. 打印

18.1. 打印命令 lpr

# lpr unixtoolbox.ps                 # 用默认打印机打印
# export PRINTER=hp4600              # 更改默认打印机
# lpr -Php4500 #2 unixtoolbox.ps     # 指定打印机 hp4500 并打印 2 份
# lpr -o Duplex=DuplexNoTumble ...   # 启用双面打印
# lpr -o PageSize=A4,Duplex=DuplexNoTumble ...
# lpq                                # 查看默认打印机的队列
# lpq -l -Php4500                    # 详细显示打印机队列信息
# lprm -                             # 删除所有打印机内的用户打印作业
# lprm -Php4500 3186                 # 删除作业 3186. 可使用 lpq 查看作业号
# lpc status                         # 列印所有可用打印机
# lpc status hp4500                  # 如果打印机在线, 查看其状态和列队长度
# gs -dSAFER -dNOPAUSE -sDEVICE=deskjet -sOutputFile=\|lpr file.pdf

19. 数据库

19.1. PostgreSQL

19.1.1. 更改 root 用户或其它用户的密码

# psql -d template1 -U pgsql
> alter user pgsql with password 'pgsql_password';

19.1.2. 创建用户和数据库

# createuser -U pgsql -P bob         # -P 会请求一个秘密
# createdb -U pgsql -O bob bobdb     # 新数据库 bobdn 的所有者是 bob
# dropdb bobdb                       # 删除数据库 bobdb
# dropuser bob                       # 删除用户 bob

19.1.3. 允许远程访问

文件 $PGSQL_DATA_D/pg_hba.conf 定义了访问控制. 举例:

# TYPE  DATABASE    USER        IP-ADDRESS        IP-MASK          METHOD
host    bobdb       bob        212.117.81.42     255.255.255.255   password
host    all         all        0.0.0.0/0                           password

19.1.4. 备份和恢复

# pg_dump --clean dbname > dbname_sql.dump
# psql dbname < dbname_sql.dump
# pg_dumpall --clean > full.dump
# psql -f full.dump postgres

19.2. MySQL

19.2.1. 更改 mysql root 用户或其它用户的密码

  1. 方法 1
    # /etc/init.d/mysql stop
    # killall mysqld
    # mysqld --skip-grant-tables
    # mysqladmin -u root password 'newpasswd'
    # /etc/init.d/mysql start
    
  2. 方法 2
    # mysql -u root mysql
    mysql> UPDATE USER SET PASSWORD=PASSWORD("newpassword") where user='root';
    mysql> FLUSH PRIVILEGES;
    mysql> quit
    

19.2.2. 创建用户和数据库

# mysql -u root mysql
mysql> CREATE DATABASE bobdb;
mysql> GRANT ALL ON *.* TO 'bob'@'%' IDENTIFIED BY 'pwd';
mysql> DROP DATABASE bobdb;
mysql> DROP USER bob;
mysql> DELETE FROM mysql.user WHERE user='bob and host='hostname';
mysql> FLUSH PRIVILEGES;

19.2.3. 允许远程访问

# mysql -u root mysql
mysql> GRANT ALL ON bobdb.* TO bob@'xxx.xxx.xxx.xxx' IDENTIFIED BY 'PASSWORD';
mysql> REVOKE GRANT OPTION ON foo.* FROM bar@'xxx.xxx.xxx.xxx';
mysql> FLUSH PRIVILEGES;

19.2.4. 备份和恢复

# mysqldump -u root -psecret --add-drop-database dbname > dbname_sql.dump
# mysql -u root -psecret -D dbname < dbname_sql.dump
# mysqldump -u root -psecret --add-drop-database --all-databases > full.dump
# mysql -u root -psecret < full.dump

19.3. SQLite

19.3.1. 备份和恢复

# sqlite database.db .dump > dump.sql              # 备份
# sqlite database.db < dump.sql                    # 恢复

19.3.2. 转换 2.x 到 3.x 数据库

sqlite database_v2.db .dump | sqlite3 database_v3.db

20. 磁盘限额

20.1. Linux 设置

添加 usrquota 到 fstab 的挂载类型中:

/dev/sda2     /home    reiserfs     rw,acl,user_xattr,usrquota 1 1
# mount -o remount /home
# quotacheck -vum /home
# chmod 644 /home/aquota.user
# quotaon -vu /home
# quota -v

20.2. FreeBSD 设置

添加限额到 fstab 选项(是 userquota, 而不是 usrquota)中:

/dev/ad0s1d    /home    ufs     rw,noatime,userquota    2  2
# mount /home

/etc/rc.conf 中启用磁盘限额并开启 quota 服务.

enable_quotas="YES"
check_quotas="YES"
# /etc/rc.d/quota start

20.3. 分配限额

# edquota -u colin

20.4. 给许多用户分配限额

# edquota -p refuser `awk -F: $3 > 499 {print $1}' /etc/passwd`
# edquota -p refuser user1 user2     # 复用给 2 个用户

20.5. 检查

# quota -u colin                     # 查看用户的限额
# repquota /home                     # 所有用户在这个分区上的限额情况

21. SHELLS

过滤器(Filter)非常有用并且可用于管道(pipe):

grep
模式匹配
sed
查找并替换字符串或字符
cut
从一个标记开始打印所指定列数据
sort
按字母或数字排序
uniq
删除一个文件中重复行

21.1. bash

# cmd 1> file                         # 重定向标准输出到 file.
# cmd 2> file                         # 重定向标准错误输出到 file.
# cmd 1>> file                        # 重定向标准输出并追加到 file.
# cmd &> file                         # 重定向标准输出和标准错误输出到 file.
# cmd >file 2>&1                      # 重定向标准错误输出到标准输出然后重定向到 file.
# cmd1 | cmd2                         # cmd1 的输出通过管道连接到 cmd2 的输入
# cmd1 2>&1 | cmd2                    # cmd1 的输出和错误输出通过管道连接到 cmd2 的输入

/.bashrc:

# in .bashrc
bind '"\e[A"':history-search-backward
bind '"\e[B"':history-search-forward
set -o emacs
set bell-style visible
PS1="\[\033[1;30m\][\[\033[1;34m\]\u\[\033[1;30m\]"
PS1="$PS1@\[\033[0;33m\]\h\[\033[1;30m\]]\[\033[0;37m\]"
PS1="$PS1\w\[\033[1;30m\]>\[\033[0m\]"
alias  ls='ls -aF'
alias  ll='ls -aFls'
alias  la='ls -all'
alias ..='cd ..'
alias ...='cd ../..'
export HISTFILESIZE=5000
export CLICOLOR=1
export LSCOLORS=ExGxFxdxCxDxDxBxBxExEx

21.2. tcsh

# cmd >& file                         # 重定向标准输出和标准错误输出到 file.
# cmd >>& file                        # 追加标准输出和标准错误输出到 file.
# cmd1 | cmd2                         # cmd1 的输出通过管道连接到 cmd2 的输入
# cmd1 |& cmd2                        # cmd1 的输出和错误输出通过管道连接到 cmd2 的输入

/.cshrc:

# in .cshrc
alias  ls      'ls -aF'
alias  ll      'ls -aFls'
alias  la      'ls -all'
alias  ..      'cd ..'
alias  ...     'cd ../..'
set   prompt    = "%B%n%b@%B%m%b%/> "
set   history   =  5000
set   savehist  = ( 6000 merge )
set   autolist
set   visiblebell
bindkey -e
bindkey -k up history-search-backward
bindkey -k down history-search-forward
setenv CLICOLOR 1
setenv LSCOLORS ExGxFxdxCxDxDxBxBxExEx

22. 脚本

22.1. 基础

22.1.1. 变量和参数

MESSAGE="Hello World"
PI=3.1415
N=8
TWON=`expr $N * 2`
TWON=$(($N * 2))
TWOPI=`echo "$PI * 2" | bc -l`
ZERO=`echo "c($PI/4)-sqrt(2)/2" | bc -l`

22.1.2. 命令行参数

$0, $1, $2, ...
$0 命令本身
$#
命令参数个数
$*
所有参数(也可以是 $@)

22.1.3. 一些特殊的变量

$$
当前进程 ID
$?
最后命令退出状态码
(no term)
`pwd`
${mypath##*/}
只显示文件名
${mypath%%.*}
除了扩展名的全路径
(no term)
var2=${var:=string}

22.1.4. 结构控制

for file in `ls`
do
    echo $file
done

count=0
while [ $count -lt 5 ]; do
    echo $count
    sleep 1
    count=$(($count + 1))
done

myfunction() {
    find . -type f -name "*.$1" -print
}
myfunction "txt"

MYHOME=/home/colin
cat > testhome.sh << _EOF
# 所有_EOF前的代码都会进入到 testhome.sh 文件中去
if [ -d "$MYHOME" ] ; then
    echo $MYHOME exists
else
    echo $MYHOME does not exist
fi
_EOF
sh testhome.sh

22.2. Bourne 脚本实例

#!/bin/sh
# 此脚本可以创建一份供双面打印机打印的 PDF 格式的书
if [ $# -ne 1 ]; then                        # 检查参数是否等于 1
  echo 1>&2 "Usage: $0 HtmlFile"
  exit 1                                     # 如果不等于1, 非0退出
fi

file=$1                                      # 文件变量
fname=${file%.*}                             # 文件名变量
fext=${file#*.}                              # 文件扩展名变量

prince $file -o $fname.pdf                   # www.princexml.com
pdftops -paper A4 -noshrink $fname.pdf $fname.ps # 创建 postscript 小册子
cat $fname.ps |psbook|psnup -Pa4 -2 |pstops -b "2:0,1U(21cm,29.7cm)" > $fname.book.ps

ps2pdf13 -sPAPERSIZE=a4 -sAutoRotatePages=None $fname.book.ps $fname.book.pdf
exit 0                                       # exit 0 意为成功

22.3. 一些 sed 命令

sed 's/string1/string2/g'                    # 替换 string1 为 string2
sed -i 's/wroong/wrong/g' *.txt              # 用 g 替换所有返回的单词
sed 's/\(.*\)1/\12/g'                        # 修改 anystring1 为 anystring2
sed '/<p>/,/<\/p>/d' t.xhtml                 # 删除以 <p> 开始, 以 </p> 结尾的行
sed '/ *#/d; /^ *$/d'                        # 删除注释和空行
sed 's/[ \t]*$//'                            # 删除行尾空格 (使用 tab 代替 \t)
sed 's/^[ \t]*//;s/[ \t]*$//'                # 删除行头尾空格
sed 's/[^*]/[&]/'                            # 括住首字符 [] top -> [t]op
sed = file | sed 'N;s/\n/\t/' > file.num     # 为文件添加行号

22.4. 正则表达式

[\^$.|?*+()
特殊字符
\
转义特殊字符
*
重复前项 0 次或多次
.
单个字符除换行符
.*
匹配 0 个或多个字符
^
匹配字符串行开始处
$
匹配字符串行结尾处
.$
匹配字符串行最后一个字符
^ $
匹配单个空格的行
[^A-Z]
匹配任何以 A-Z 字符开始的行

22.5. 一些实用命令

sort -t. -k1,1n -k2,2n -k3,3n -k4,4n         # 排序 IPv4 格式的 IP 地址
echo 'Test' | tr '[:lower:]' '[:upper:]'     # 转换成大写
echo foo.bar | cut -d . -f 1                 # 返回 foo
PID=$(ps | grep script.sh | grep bin | awk '{print $1}')
PID=$(ps axww | grep [p]ing | awk '{print $1}')
IP=$(ifconfig $INTERFACE | sed '/.*inet addr:/!d;s///;s/ .*//')   # Linux
IP=$(ifconfig $INTERFACE | sed '/.*inet /!d;s///;s/ .*//')        # FreeBSD
if [ `diff file1 file2 | wc -l` != 0 ]; then [...] fi             # 文件改变了?
cat /etc/master.passwd | grep -v root | grep -v \*: | awk -F":" \
'{ printf("%s:%s\n", $1, $2) }' > /usr/local/etc/apache2/passwd

testuser=$(cat /usr/local/etc/apache2/passwd | grep -v \
root | grep -v \*: | awk -F":" '{ printf("%s\n", $1) }' | grep ^user$)
:(){ :|:& };:                                # bash fork 炸弹
tail +2 file > file2                         # 删除文件的第一行
# ls *.cxx | awk -F. '{print "mv "$0" "$1".cpp"}' | sh
# ls *.c | sed "s/.*/cp & &.$(date "+%Y%m%d")/" | sh
# rename .cxx .cpp *.cxx
# for i in *.cxx; do mv $i ${i%%.cxx}.cpp; done

23. 编程

23.1. C 基础

strcpy(newstr,str)
拷贝 str 到 newstr
expr1 ? expr2 : expr3
if (expr1) expr2 else expr3
x = (y > z) ? y : z;
if (y > z) x = y; else x = z;
int a[]={0,1,2};
初始化数组
int a[2][3]={{1,2,3},{4,5,6}};
初始化二维数组
sprintf(str, "%d", i);
从 i 转换成 char str

23.2. C 实例

simple.c:

#include <stdio.h>
main() {
    int number=42;
    printf("The answer is %i\n", number);
}

编译:

# gcc simple.c -o simple
# ./simple

23.3. C++ 基础

*pointer
指向对象的指针
&obj
对象 obj 的地址
obj.x
类(对象) obj 成员 x
pobj->x
指针 pobj 指向类(对象)成员 x

23.4. C++ 实例

23.4.1. IPv4 class

IPv4.h:

#ifndef IPV4_H
#define IPV4_H
#include <string>

namespace GenericUtils {
class IPv4 {
public:
    IPv4();
    ~IPv4();
    std::string IPint_to_IPquad(unsigned long ip);
};
}
#endif // IPV4_H

IPv4.cpp:

#include "IPv4.h"
#include <string>
#include <sstream>
using namespace std;
using namespace GenericUtils;

IPv4::IPv4() {}
IPv4::~IPv4() {}
string IPv4::IPint_to_IPquad(unsigned long ip) {
    ostringstream ipstr;
    ipstr << ((ip &0xff000000) >> 24)
          << "." << ((ip &0x00ff0000) >> 16)
          << "." << ((ip &0x0000ff00) >> 8)
          << "." << ((ip &0x000000ff));
    return ipstr.str();
}

23.4.2. 程序 simplecpp.cpp

#include "IPv4.h"
#include <iostream>
#include <string>
using namespace std;

int main (int argc, char* argv[]) {
    string ipstr;
    unsigned long ipint = 1347861486;
    GenericUtils::IPv4 iputils;
    ipstr = iputils.IPint_to_IPquad(ipint);
    cout << ipint << " = " << ipstr << endl;

    return 0;
}

编译和执行:

# g++ -c IPv4.cpp simplecpp.cpp
# g++ IPv4.o simplecpp.o -o simplecpp.exe
# ./simplecpp.exe
# ldd /sbin/ifconfig

23.5. 简单的 Makefile

CC = g++
CFLAGS = -O
OBJS = IPv4.o simplecpp.o

simplecpp: ${OBJS}
        ${CC} -o simplecpp ${CFLAGS} ${OBJS}
clean:
        rm -f ${TARGET} ${OBJS}

24. 在线帮助

24.2. 其他 Unix/Linux 参考

Author: Colin Barschel and Greco Shi

Created: 2025-11-18 Tue 08:56