后浪笔记一零二四

Bash默认使用Emacs的快捷方式,可以通过set -o vi让它使用vi的快捷键
安全删除一个文件或者文件夹:

1
2
3
4
5
6
delete_safe() {
  if [ -e /tmp/$1 ];then
    rm -rf /tmp/$1
  fi
  mv $1 /tmp/$1
}

1. login shell

① /etc/passwd文件 登录时系统启动的shell依赖于用户账户的配置。
/etc/passwd文件包含了所有系统用户账户列表以及每个用户的基本配置信息。
以下是从/etc/passwd文件中取出的样例条目:
dacheg:x:1000:1000:dacheg,,,:/home/dacheg:/bin/bash
root:x:0:0:root:/root:/bin/bash
每个条目包含7个字段,字段之间用冒号分隔
(系统登录名:用户密码:用户账户的UID:用户账户的GID:用户账户的文本描述:用户HOME目录的位置:用户的默认shell)。
系统使用字段中的数据来赋予用户账户某些特定特性。

  1. 所有的密码字段都被设置为了x,这并不是说所有的用户账户都有相同的密码。
    在早期的linux上,/etc/passwd文件里有加密后的用户密码。
    但鉴于很多程序都需要访问/etc/passwd文件获取用户信息,这就成了一个安全隐患,所以将所有的密码字段都设置为了x。
    现在,绝大多数linux系统都将用户密码保存在另一个单独的文件中/etc/shadow。
  2. root用户账户是linux系统管理员,固定分配给它的UID是0。
    在安全成为一个大问题之前,所有的服务都属于root账户,遗憾的是,如果有非授权的用户攻陷了这些服务中的一个,他立刻就能作为root用户进入系统。
    为了防止发生这种情况,现在运行在linux服务器后台的几乎所有的服务都是用自己的账户登录。
    这样的话,即使有人攻入了某个服务,也无法访问整个系统。
    所以,在/etc/passwd文件中除了root用户,linux系统还会为各种各样的功能创建不同的用户账户,而这些账户并不是真的用户,也就是说不能登录系统。这些账户叫做系统账户(使用useradd命令的-r参数来创建系统账户),是系统上运行的各种服务进行访问资源用的特殊账户。

linux为系统账户预留了500以下的UID值。有些服务甚至要用特定的UID才能正常工作。为普通用户创建账户时,大多数linux系统会从500开始,将第一个可用UID分配给这个账户(并非所有的linux发行版都是这样)。

② /etc/shadow文件 在/etc/shadow文件中每条记录中都有9个字段:

  1. 与/etc/passwd文件对应的登录名。
  2. 加密后的密码。
  3. 上次修改密码的那天距离1970年1月1日有多少天。
  4. 多少天后才能更改密码
  5. 多少天后必须更改密码
  6. 密码过期前提前多少天提醒用户更改密码
  7. 密码过期后多少天禁用用户账户
  8. 用户账户被禁用的那天距离1970年1月1日有多少天
  9. 预留字段给将来使用

③ 在你登录linux系统启动一个bash shell时,默认情况下bash会在几个文件中查找命令。这些文件叫做启动文件(也可以叫做环境文件)。bash检查的启动文件取决于你启动bash shell的方式。启动bash shell有3种方式:交互式非登录shell,交互式登录shell,非交互式shell。

  1. 交互式登录shell
    交互式登录shell会从3个不同的启动文件里读取命令: /etc/profile, $HOME/.bashrc, ($HOME/.bash_profile、$HOME/.bash_login和$HOME/.profile)当中选择一个。 shell会按照下列顺序,运行第一个被找到的文件,剩下的则被忽略:$HOME/.bash_profile, $HOME/.bash_login, $HOME/.profile,并且$HOME/.bashrc会被source到这三个文件中来。

$0在非交互式脚本中,代表的脚本的名称。在交互式shell中,代表的是根sprocess的名称。
除了在首次登录linux的时候会执行login shell(非图形界面,使用ctrl+alt+F3~6进入命令界面),还可以使用下面的命令来执行login shell:

1
2
3
4
5
$ su - | su -l | su --login | su -l USERNAME | \
  su --login USERNAME | sudo -i

# 如果echo $0命令的输出有一个前置的-,就说明是一个login shell,
# 例如-bash, -su
  1. 交互式非登录shell
    交互式非登录shell不会访问/etc/profile文件,只会检查用户HOME目录中的.bashrc文件。 使用命令$ su | su USERNAME进入的shell属于Non Login Shell,使用ubuntu图形终端(Ctrl+Alt+T)进入的交互式shell也属于Non Login Shell。

  2. 非交互式shell
    当shell启动一个非交互式shell进程时,它会检查BASH_ENV环境变量,来查看要执行的启动文件。
    如果BASH_ENV变量没有设置,shell脚本到哪里去获得它们的环境变量呢?记住: 子shell会继承父shell导出过的变量。

在创建shell脚本文件时,必须在文件的第一行指定要使用的shell。其格式为:#!/bin/bash。在通常的shell脚本中,井号用作注释行。shell并不会处理shell脚本中的注释行。然而,shell脚本文件的第一行是个例外,#后面的感叹号会告诉shell用哪个shell来运行脚本。

  1. sudo执行脚本如何做到不重置环境变量

问题

1
2
3
4
5
$ export hello=world
$ env|grep world
hello=world
$ sudo env|grep world
$

原因

这是因为sudo会重置当前环境变量,原始umask值为022,原始PATH值为/sbin:/bin:/usr/sbin:/usr/bin

5.x的内核,原始PATH值为/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin。

解决1:

在/etc/sudoers 可以配置执行sudo时,哪些环境变量进行保留,当然也全部保留

Defaults    env_reset, timestamp_timeout=1440 #重置环境变量
Defaults    !env_reset, timestamp_timeout=1440 #保留全部环境变量

解决2:

sudo -E env|grep hello
-E, --preserve-env            preserve user environment when running command
  1. 环境变量的持久化
    不要修改/etc/profile文件,因为系统升级之后,这个文件也会跟着更新。
    最好是在/etc/profile.d目录中创建一个以.sh结尾的文件。
    把所有新的或修改过的全局环境变量设置放在这个文件中。

  2. PATH变量的检索顺序

当前目录:在某些情况下(如在 Unix/Linux 系统中),如果命令前有 ./ 前缀,则会先在当前目录下查找。
PATH 变量中的目录:然后,系统会依次检查 PATH 变量中列出的每一个目录,直到找到第一个匹配的可执行文件为止。
内部命令:如果在所有指定的路径中都没有找到该命令,而该命令是 shell 的内部命令(如 cd、echo 等),则 shell 会直接执行这个内部命令。
错误消息:如果命令既不是内部命令,也没有在 PATH 中找到对应的可执行文件,则会向用户显示一条错误消息,说明命令未找到。

  1. 执行sudo命令,还能获取到当前用户的用户名么?

使用SUDO_USER环境变量来获取,或者使用logname命令来获取。

注意,不能直接使用sudo echo $SUDO_USER命令来获取,因为$SUDO_USER会在执行前被替换掉,替换成当前shell中SUDO_USER环境变量的值,这个时候sudo还没有执行。

需要将echo $SUDO_USER放到一个脚本里,例如:

1
2
3
4
5
$ cat <<'EOF' > test.sh
> echo $SUDO_USER
> EOF

$ sudo sh test.sh

2.bash手册

linux手册页惯用的节名:

描述
Name 显示命令名和一段简短的描述
Synopis 命令的语法
Configuration 命令配置信息
Description 命令的一般性描述
Options 命令选项描述
Exit Status 命令的退出状态指示
Return Value 命令的返回值
Errors 命令的错误信息
Environment 描述所使用的环境变量
Files 命令用到的文件
Versions 命令的版本信息
Conforming To 命令所遵从的标准
Notes 其他有帮助的资料
Bugs 提供提交bug的途径
Example 展示命令的用法
Authors 命令开发人员的信息
Copyright 命令源代码的版权状况
See Also 与该命令相关的其他命令

linux手册页的内容区域

区域号 所涵盖的内容
1 可执行程序或shell命令 bin
2 系统调用 sys-call
3 库调用 lib-call
4 特殊文件 special-file
5 文件格式与约定 file-format
6 游戏 game
7 概览、约定及杂项 overview
8 超级用户和系统管理员命令 super-bin
9 内核例程 kernel-routine

一个命令偶尔会在多个内容区域都有对应的手册页,你可以只看各部分内容的简介:输入man 1 intro阅读第一部分,输入man 2 intro阅读第二部分,输入man 3 intro阅读第3部分。

3. FHS(filesystem hierarchy standard, http://www.pathname.com/fhs)

常见的linux目录名称

目录 用途
/ 虚拟目录的根目录。通常不会在这里存储文件
/bin 二进制目录,存放许多用户级的GNU工具
/boot 启动目录,存放启动文件
/dev 设备目录,linux在这里创建设备节点
/etc 系统配置文件目录
/home 主目录,linux在这里创建用户目录
/lib 库目录,存放系统和应用程序的库文件
/media 媒体目录,可移动媒体设备的常用挂载点
/mnt 挂载目录,另一个可移动媒体设备的常用挂载点
/opt 可选目录,常用于存放第三方软件包的数据文件
/proc 进程目录,存放现有硬件及当前进程的相关信息, 查看cpu核心数,cat /proc/cpuinfo \| grep processor \| wc -l
/root root用户的主目录
/sbin 系统二进制目录,存放许多GNU管理员级工具
/run 运行目录,存放系统运行时的运行时数据,/var/run是指向/run的软链。/run是挂载到tmpfs文件系统的,也就是内存文件系统,断电重启后数据会丢失
/srv 服务目录,存放本地服务的相关文件
/sys 系统目录,存放系统硬件信息的相关文件
/tmp 临时目录,可以在该目录中创建和删除临时工作文件
/usr 用户二进制目录,大量用户级的GNU工具和数据文件都存储在这里
/var 可变目录,用以存放经常变化的文件,比如日志文件

在安装linux操作系统的时候,会使用第一块硬盘作为根驱动器,并在根驱动器上创建遵循FHS的核心虚拟目录。 对之后手动创建的非核心虚拟目录,都可以作为其他驱动器的挂载点(mount point)。

① mount命令 默认情况下,mount命令会输出当前系统上挂载的设备列表。

1
2
3
4
5
$ mount
sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime)
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
udev on /dev type devtmpfs (rw,nosuid,relatime,size=2971648k,nr_inodes=742912,mode=755)
...

mount命令提供如下4部分信息:媒体的设备文件名(或设备文件路径),媒体挂载到虚拟目录的挂载点,文件系统类型,(已挂载媒体的访问状态)。
下面是手动挂载媒体设备的基本命令:
mount -t type device directroy
type参数指定了磁盘被格式化的文件系统类型。linux可以识别非常多的文件系统类型。如果是和windowsPC共用这些存储设备,通常得使用下列文件系统类型。
vfat: Windows长文件类型(小文件存储)
ntfs: WindowsNT,XP,Vista以及windows7中广泛使用的高级文件系统(大文件存储)

mount命令的参数

参数 描述
-a 挂载/etc/fstab文件中指定的所有文件系统
-f 使mount命令模拟挂载设备,但并不真的挂载
-F 和-a参数一起使用时,会同时挂载所有文件系统
-v 详细模式,将会说明挂载设备的每一步
-I 不启用任何/sbin/mount.filesystem下的文件系统帮助文件
-l 给ext2、ext3或XFS文件系统自动添加文件系统标签
-n 挂载设备,但不注册到/etc/mtab已挂载设备文件中
-p num 进行加密挂载时,从文件描述符num中获得密码短语
-s 忽略该文件系统不支持的挂载选项
-r 将设备挂载为只读的
-w 将设备挂载为可读写的(默认参数)
-L label 将设备按指定的label挂载
-U uuid 将设备按指定的uuid挂载
-O 和-a参数一起使用,限制命令只作用到特定的一组文件系统上
-o 给文件系统添加特定的选项

-o参数允许在挂载文件系统时添加一些以逗号分隔的额外选项。以下为常用的选项。 ro: 以只读形式挂载。 rw: 以读写形式挂载。 user: 允许普通用户挂载文件系统 check=none: 挂载文件系统时不进行完整性检验。 loop: 挂载一个文件。

要强制linux启动时自动挂载新的文件系统,可以将其添加到/etc/fstab文件中。

/dev/mapper/centos-root                      /       xfs     defaults 0 0
UUID=398848b7-fad0-419e-9a68-9ffb0907635f    /boot   xfs     defaults 0 0
/dev/mapper/centos-swap                      swap    swap    defaults 0 0
/data/                               /mnt/disks/data none    bind     0 0
各个字段的含义可以使用man fstab来查看

② umount命令 umount命令的格式:umount [directory | device]

umount命令支持通过挂载点或者是设备文件名(设备文件路径)来指定要卸载的设备。 如果有任何程序正在使用设备上的文件,系统就不会允许你卸载它。 例如有进程还在访问该设备或使用该设备上的文件。这时可用lsof命令获得使用它的进程信息,然后停止该进程或者让该进程停止使用该设备。 lsof命令的用法很简单: lsof /path/to/device/或者lsof /path/to/mount/point

③ df命令(report file system disk space usage)

1
2
3
$ df
文件系统           1K-块     已用      可用 已用% 挂载点
rootfs         498658820 63844328 434814492   13% /
  1. 设备文件的文件路径
  2. 能容纳多少个1024字节大小的块
  3. 已用了多少个1024字节大小的块
  4. 还有多少个1024字节大小的块可用
  5. 已用空间所占的比例
  6. 挂载点

-h参数:以人类易读的方式展示磁盘空间。

④ du命令(estimate估计 file space usage) 用于快速判断系统上某个目录下是不是有超大文件。

1
2
3
4
5
$ du 
484 ./.gstreamer-0.10 
8 ./Templates 
8 ./Download 
8 ./.ccache/7/0 

每行输出左边的数值是每个文件或目录占用的磁盘块数。 注意,这个列表是从目录层级的最底部开始,然后按文件、子目录、目录逐级向上的。

默认情况下,du命令的作用并不大,因为输出的列表实在太长了。下面是能让du命令用起来更方便的几个命令行参数。

参数 作用
-c 显示所有已列出文件中的大小
-h 按用户易读的格式输出大小,即用K替代千字节,用M替代兆字节,用G替代吉字节
-s 显示每个输出参数的总计

⑤ 给u盘创建mbr(lsblk)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
## 假设我的U盘为/dev/sdc,仅有/dev/sdc1分区(/dev/sdc是设备文件路径,/dev/sdc1末尾的1表示分区号, 可以使用lsblk命令查看)。

## 第一步,卸载U盘,进行分区并格式化
umount /dev/sdc1
fdisk /dev/sdc #查询存储设备信息(p),删除旧的分区(d),创建新的分区(n),写入硬盘(w)。分区分为主分区和扩展分区,主分区可以被文件系统直接格式化,扩展分区可以容纳逻辑分区,扩展分区出现的原因是每个存储设备上只能有4个主分区,可以通过创建多个扩展分区,然后在扩展分区中创建逻辑分区进行扩展。
mkfs.fat -F 32 /dev/sdc1 # 格式化sdc1分区为fat32,-F参数为强制格式化。

## 第二步,写入mbr
## ms-sys工具下载地址:http://ms-sys.sourceforge.net
ms-sys -3 /dev/sdc1 #向sdc1分区的boot sector写入fat32 dos boot record;
ms-sys -d /dev/sdc # 向/dev/sdc(u盘设备)的第一扇区写入dos mbr

## 第三步,copy镜像
mount -o loop ~/win8.1.iso /mnt/ISO
mount /dev/sdc1 /mnt/USB
cp -r /mnt/ISO/* /mnt/USB
umount /dev/sdc1 /mnt/ISO

⑥ fsck命令 用于检查和修复大部分linux文件系统。

⑦ 逻辑卷管理(fdisk) linux逻辑卷管理器(logical volume manager, LVM)可以让你在无需重建整个文件系统的情况下,轻松地管理磁盘空间。

  1. 逻辑卷管理布局

在逻辑卷管理的世界里,硬盘称为物理卷(physical volume, PV)。每个物理卷都会映射到硬盘上特定的物理分区。 多个物理卷集中在一起可以形成一个卷组(volume group, VG)。逻辑卷管理系统将卷组视为一个物理硬盘,但事实上卷组可能是由分布在多个物理硬盘上的多个物理分区组成的。 在卷组之上可以创建逻辑卷(logical volume, LV),逻辑卷为linux提供了创建文件系统的分区环境。linux系统将逻辑卷视为物理分区。所以可以使用任意一种标准的linux文件系统来格式化逻辑卷,然后将它加入到Linux虚拟目录中的某个挂载点。

LVM.png

  1. 创建LVM

第一步,定义物理卷

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
## 使用fdisk将硬盘上的物理分区转换为linux LVM使用的物理卷区段。
$ fdisk  <设备文件路径名>
[...] 
Command (m for help): t 
Selected partition 1 
Hex code (type L to list codes): 8e # 分区类型8e表示这个分区将会被用作LVM系统的一部分。
Changed system type of partition 1 to 8e (Linux LVM) 
Command (m for help): p 
Disk /dev/sdb: 5368 MB, 5368709120 bytes 
255 heads, 63 sectors/track, 652 cylinders 
Units = cylinders of 16065 * 512 = 8225280 bytes 
Sector size (logical/physical): 512 bytes / 512 bytes 
I/O size (minimum/optimal): 512 bytes / 512 bytes 
Disk identifier: 0xa8661341 
  Device Boot Start End Blocks Id System 
/dev/sdb1 1 262 2104483+ 8e Linux LVM 
Command (m for help): w 
The partition table has been altered! 
Calling ioctl() to re-read partition table. 
Syncing disks. 

$ sudo pvcreate /dev/sdb1
$ pvdisplay /dev/sdb1

第二步,创建卷组 创建卷组并命名为Vol1:sudo vgcreate Vol1 /dev/sdb1 查看创建进度:sudo vgdisplay Vol1 扩容卷组Vol1: sudo vgextend Vol1 /dev/sdb2

第三步,创建逻辑卷 lvcreate命令要求至少输入一些选项。

选项 长选项名 描述
-c –chunksize 指定快照逻辑卷的单位大小
-C –contiguous 设置或重置连续分配策略
-i –scripts 指定条带数
-I –scripesize 指定每个条带的大小
-l –extents 指定分配给新逻辑卷的逻辑区段数,或者要用的逻辑区段的百分比
-L –size 指定分配给新逻辑卷的硬盘大小
-L –minor 指定设备的块设备号
-m –mirrors 创建逻辑卷镜像
-M –persistent 让次设备号一直有效
-n –name 指定新逻辑卷的名称
-p –permission 为逻辑卷设置读写权限
-r –readahead 设置预读扇区数
-R –regionsize 指定将镜像分成多大的区
-s snapshot 创建快照逻辑卷
-Z –zero 将新逻辑卷的前1KB数据设置为零
1
2
3
$ sudo lvcreate -l 100%FREE -n lvtest Vol1
# 查看创建情况
$ sudo lvdisplay Vol1

第四步,创建文件系统

1
2
$ sudo mkfs.ext4 /dev/Vol1/lvtest
$ sudo mount /dev/Vol1/lvtest /mnt/my_partition

第五步,逻辑卷扩容 (永远不要对LVM进行缩容,缩容就是个坑)

# 扩展pv, 其中/dev/Vol1/lvtest的命名规范是/dev/卷组名/逻辑卷名
# !!!!! 扩容只有一次机会,在扩容之前,一定要确认清楚
$ sudo lvextend -l +100%FREE /dev/Vol1/lvtest

# 扩展pv后,它的挂载点/mnt/my_partition并没有同步增大
# ext系列的文件系统使用resize2fs来实现同步
# xfs文件系统使用xfs_growfs来实现同步
$ xfs_growfs /dev/Vol1/lvtest

第六步,永远不要使用的步骤:vgreduce, lvreduce

如何使用dmsetup命令处理先删pv再删vg的情况?

⑧ 使用mdadm实现软raid MegaCli不开源,需要到broadcom公司的网站上去下载,不建议使用。

4.基本的文件操作

① ls命令 ls命令输出的列表是按列排序的。注意,如果用户用的是支持彩色的终端仿真器,ls命令还可以用不同的颜色来区分不同类型的文件。LS_COLORS环境变量控制这个功能。如果没有安装彩色终端仿真器,可以用-F参数来区分文件和目录。目录名后加了正斜线/,可执行文件的后面加了星号。 -R 递归选项。它会列出当前目录下包含的子目录中的文件。 -l 会以长列表格式输出文件信息。包含这些信息: 1.文件类型(也可以使用file命令来确认文件类型),比如目录(d),文件(-),字符型文件(c)或块设备(b),链接(l),网络设备(n); 2.文件的权限,可读(r),可写(w),可执行(x),共有三组安全级别(属主,属组,系统的其他用户); 3.文件的硬链接总数; 4.文件属主的用户名; 5.文件属组的组名; 6.文件的大小(以字节为单位); 7.文件的上次修改时间; 8文件名或目录名。 -d(directory) 只列出目录本身的信息,不列出其中的内容

② 其他文件命令 touch, cp, mv, rm(使用mv filename /tmp来替代rm命令), file(查看文件类型), cat(顺序展示文件内容), tac(逆序展示文件内容), more, less, tail, head。 mkdir rmdir(只能删除空目录) tree(展示目录树)

③ shopt

1
2
3
# 删除当前目录下除了.tar.gz和.py结尾的其他文件
$ shopt -s extglob
$ rm -rf !(*.py|*.tar.gz)

④ 链接 符号链接就是一个实实在在的文件,它指向存放在某个虚拟目录下的某个文件。 inode编号是由内核分配给文件系统的每个对象,用来唯一标识它们的。 可以使用ls -i查看链接文件的inode编号,会发现链接文件和被链接文件的inode编号是不一样的。

硬链接和原始文件本质上是同一个文件, 所以它们的inode编号是一致的。 所以,硬链接文件和原始文件必须在同一个存储媒体中,否则就使用符号链接。

注意在创建链接的时候,要使用绝对路径。

5. 用户管理

① useradd useradd命令使用系统的默认值以及命令行参数来设置用户账户。系统的默认值被设置在/etc/default/useradd文件中。 可以使用加入了-D选项的useradd命令查看所用linux系统中的这些默认值。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
$ useradd -D
GROUP=100              # 新用户会被添加到GID为100的公共组
HOME=/home             # 新用户的HOME目录将会位于/home/loginname;
INACTIVE=-1            #新用户账户密码在过期后不会被禁用
EXPIRE=                # 新用户账户未被设置过期日期
SHELL=/bin/sh         # 新用户账户将bash shell作为默认shell
SKEL=/etc/skel         # 系统会将/etc/skel目录下的内容复制到用户的HOME目录下
CREATE_MAIL_SPOOL=no # 系统为该用户账户在mail目录下(/var/mail)创建一个用于接受邮件的文件。

# 可以在-D参数后跟上一个指定的值来修改系统默认的新用户设置。
# 1. -b default_home:    更改默认的创建用户HOME目录的位置
# 2. -e expiration_date: 更改默认的新用户的过期日期
# 3. -f inactive:        更改默认的新用户从密码过期到账户被禁用的天数
# 4. -g group:           更改默认的组名称或GID
# 5. -s shell:           更改默认的登录shell

创建用户的时候,可以使用如下的option来设置用户属性。

参数 描述
-c comment 给新用户添加备注
-d home_dir 为主目录指定一个名字(默认值是登录名作为主目录名)
-e expire_date 用YYYY-MM-DD格式指定一个账户过期的日期
-f inactive_days 指定这个账户密码过期后多少天这个账户被禁用;0表示密码一过期就立即禁用,1表示禁用这个功能
-g initial_group 指定用户登录组的GID或组名
-G group … 指定用户除登录组之外所属的一个或多个附加组
-k 必须和-m一起使用,将/etc/skel目录的内容复制到用户的HOME目录
-m 创建用户的HOME目录, 默认不会创建HOME目录
-M 不创建用户的HOME目录(当默认设置里要求创建时才使用这个选项)
-n 创建一个与用户登录名同名的新组
-r 创建系统账户
-p passwd 为用户账户指定默认密码,简单的密码不会生效也不提示,要想有提示,就用root用户执行 passwd <新用户名>,
-s shell 指定默认的登录shell
-u uid 为账户指定唯一的UID

② userdel 默认情况下,userdel命令只会删除/etc/passwd文件中的用户信息,而不会删除系统中属于该账户的任何文件。 如果加上-r参数,userdel会删除用户的HOME目录以及邮件目录。然而,系统上仍可能存在已删除用户的其他文件。 这在有些环境中会造成问题。

③ 修改用户的6个命令

  1. usermod: 修改/etc/passwd文件中的大部分字段,还可以指定基本组以及附加组的所属关系
  • 在使用useradd命令创建用户的时候可以用-g和-G指定用户基本组和附加组
  • 基本组: 如果没有指定用户组,创建用户的时候系统会默认同时创建一个和这个用户名同名的组,这个组就是基本组。
    • 用户不能从基本组中删除。 ls -l命令显示的组就是基本组。
  • 附加组: 除了基本组之外,用户所在的其他组,都是附加组。
    • 用户可以从附加组中删除。
  1. passwd: 修改当前用户的密码
  2. chpasswd: 将含有userid:passwd对的文件重定向给该命令,可以实现批量更新密码
  3. chage: 修改密码的过期日期
  4. chfn(finger):修改用户账户的指纹信息
  5. chsh: 修改用户账户的默认登录shell

④ /etc/group文件

  • /etc/group文件有4个字段:组名,组密码,GID,属于该组的用户列表。
  • 组密码允许非组内成员通过它临时成为该组成员。
  • 系统账户用的组通常会分配低于500的GID值,而用户组的GID则会从500开始分配。
  • 属于该组的用户列表,不会包含以自己为基本组的用户。

groupadd 新增一个组。 groupmod -n new-group old-group 修改组 groupmod -g 1234 groupname 修改指定组的GID groupdel groupname 删除组

⑤ 文件权限

  1. umask命令用来设置所创建文件和目录的默认权限。
1
2
$ umask
0022
  • 第一位表示粘着位(sticky bit),后3位是八进制值。
  • 文件一开始的权限其实是666,减去022后,就变成644了。
  • 文件夹一开始的权限是777, 减去022后,就变成755了。

在大多数linux发行版中,umask值通常会设置在/etc/profile启动文件中,但是ubuntu是设置在/etc/login.defs文件中。

  1. chmod
  • 命令格式: chmod options mode file
  • options没有什么作用,主要是mode。
  • mode可以使用3位八进制权限码,还可以使用符号模式。
  • 符号模式的格式如下: [ugoa][+-=][rwxugoXst]

第一组字符:用户(u),组(g),其他(o),上述所有(a) 第三组字符: X, execute/search only if the file is a directory or already has execute permission for some user, s(set,分为setuid和setgid), set user or group ID on execution (设置可执行文件的专属权限) t, restricted(受限制的) deletion flag or stricky bit

注意: s和t放在(rwx)的第三位的x上。 系统是这样规定的,如果本来在该位上有x,则这些特殊标志显示为小写字母(s,t);否则就显示为大写字母(S,T)

setuid: 设置使文件在执行阶段具有文件所有者的权限。典型的文件是/usr/bin/passwd。如果一般用户执行该文件,则在执行过程中,该文件可以获得root权限,从而可以更改用户的密码。(放在属主3个权限位的x位上)

setgid: 设置使文件在执行阶段具有文件所有组的权限。(放在属组3个权限位的x位上)

sticky bit: 该位可以理解为防删除位(对other用户和group用户而言)。(放在other组3个权限位的x位上) 一个文件是否可以被某用户删除,主要取决于: 该用户是否对该文件具有写权限(根据u,g,o三个权限位进行判断)。如果有写权限,该用户就可以在该目录下创建和删除文件。如果不想用户删除文件,可以使用sticky bit位。

chmod 4777是设置sid, chmod 2777是设置gid, chmod 1777是设置sticky 找出所有设置为所有人可读写却没有设置sticky位的目录:find / -perm -0007 -type d 找出所有设置了suid的文件: find / -perm -4000 -type f 第一个8进制权限位的数字代表:

八进制数 含义
0 不设置特殊权限,例如 chmod 00755 <文件名>; 主要需要使用两个零,因为单个0表示八进制
1 只设置sticky
2 只设置SGID
3 只设置SGID和sticky
4 只设置SUID
5 只设置SUID和sticky
6 只设置SUID和SGID
7 设置3种权限
  1. chown和chgrp(下面的属组指的是基本组) chown username filename 改变属主 chgrp groupname filename 改变属组 chown .groupname filename chown username.groupname filename 同时改变属主和属组 chown username. newfile 如果组名和用户名一致

chown命令,-R选项配合通配符可以递归地改变子目录和文件的所属关系。 -h选项可以改变该文件的所有符号链接的所属关系

  1. getfacl控制文件的访问权限

  2. 给一个用户添加一个附加属组后,不能立刻修改拥有组权限的文件或目录,需要重新ssh或者newgrp来刷新组权限

1
2
3
4
5
6
7
$ usermod -G jiaweicheng,root jiaweicheng
$ ls -ld /test
drwxrwxr-x 8 root root 4096 Apr 13 20:35 /test
$ touch /test/abc
touch: cannot touch '/test/abc': Permission denied
$ sudo su jiaweicheng
$ touch /test/abc

6. 开关机

poweroff: shutdown now restart: shutdown -r now 定时关机: shutdown 20:01 5分钟之后关机: shutdown +5

7. 进程命令

① ps命令 默认情况下,ps命令只会显示运行在当前控制台下的属于当前用户的进程。其会展示4项信息(1.进程id,2.运行在哪个终端,3.已用的cpu时间,4.进程名)

linux系统中使用的GUN ps命令支持3种不同类型的命令行参数:

  1. Unix风格的参数,前面加单破折线
  2. BSD风格的参数,前面不加破折线
  3. GUN风格的长参数,前面加双破折线。

$ ps -ef

  1. UID: 启动这些进程的用户ID
  2. PID: 进程的进程ID
  3. PPID: 父进程的进程号(如果该进程是由另一个进程启动的)
  4. C: 进程生命周期中的CPU利用率
  5. STIME:进程启动时的系统时间
  6. TTY: 进程启动时的终端设备
  7. TIME: 运行进程需要的累计CPU时间
  8. CMD: 启动的程序名称

$ ps -l

  1. F: 内核分配给进程的系统标记。
  2. S: 进程的状态(O代表正在运行;S代表在休眠;R代表可运行,正等待运行;Z代表僵尸进程,进程已结束但父进程已不存在;T代表停止)。
  3. PRI: 进程的优先级(越大的数字代表越低的优先级)。
  4. NI: 谦让度值用来参与决定优先级。
  5. ADDR: 进程的内存地址。
  6. SZ: 假如进程被换出,所需交换空间的大致大小。
  7. WCHAN:进程休眠的内核函数的地址

② top命令 ps只能显示某个特定时间点的信息,top能实时显示进程状态。

输出的第一行:显示系统的概括,当前时间,登录的用户数,系统的平均负载(最近1分钟的,最近5分钟的,最近15分钟的,通常,如果系统的负载值超过了2,就说明系统比较繁忙了)

最后一部分:

  1. PID: 进程的ID。
  2. USER: 进程属主的名字。
  3. PR: 进程的优先级。
  4. NI: 进程的谦让度值。
  5. VIRT: 进程占用的虚拟内存总量。
  6. RES: 进程占用的物理内存总量。
  7. SHR: 进程和其他进程共享的内存总量。
  8. S: 进程的状态(D代表可中断的休眠状态,R代表在运行状态,S代表休眠状态,T代表跟踪状态或停止状态,Z代表僵化状态)。
  9. %CPU: 进程使用的CPU时间比例。
  10. %MEM: 进程使用的内存占可用内存的比例。
  11. TIME+: 自进程启动到目前为止的CPU时间总量。
  12. COMMAND:进程所对应的命令行名称,也就是启动的程序名

键入f允许你选择对输出进行排序的字段,键入d允许你修改轮询间隔。键入q可以退出top

③ kill命令 在linux中,进程之间通过信号来通信。进程的信号就是预定义好的一个消息,进程能识别它并决定忽略还是作出反应。 常用的进程信号:

信号 16进制数 描述
SIGHUP 0x1 挂起
SIGINT 0x2 中断, Ctrl+C
SIGQUIT 0x3 结束运行
SIGILL 0x4
SIGTRAP 0x5
SIGABRT/SIGIOT 0x6
SIGBUS 0x7
SIGFPE 0x8
SIGKILL 0x9 无条件终止
SIGUSR1 0xa
SIGSEGV 0xb 段错误
SIGUSR2 0xc
SIGPIPE 0xd
SIGALRM 0xe
SIGTERM 0xf 尽可能终止
SIGSTKFLT 0x10
SIGCHLD/SIGCLD 0x11
SIGCONT 0x12 在STOP或TSTP之后恢复执行
SIGSTOP 0x13 无条件停止运行,但不终止, Ctrl+Z
SIGTSTP 0x14 停止或暂停,但继续在后台运行
SIGTTIN 0x15
SIGTTOU 0x16
SIGURG 0x17
SIGXCPU 0x18
SIGXFSZ 0x19
SIGVTALRM 0x1a
SIGPROF 0x1b
SIGWINCH 0x1c
SIGIO/SIGPOLL 0x1d
SIGPWR 0x1e
SIGSYS/SIGUNUSED 0x1f
1
2
3
4
5
#查出所有的僵尸进程:
$ ps -A -o 'stat,ppid,pid,cmd' | grep -E '^[Zz]'

#如果传递的是一个正数,这个数将被视为进程 ID 用于终止进程。如果传递的是一个负数,它被视为 PGID,用于终止整个进程组。负数来自系统调用的直接定义。
$ kill -SIGTERM -- -19701

trap命令可以捕获从bash shell中传递过来的linux信号。如果脚本收到了trap命令中列出的信号,该信号不再由shell处理,而是交由本地处理。trap commands signals

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
$ cat test
#!/bin/bash
trap "echo ' Sorry! I have trapped Ctrl-C'" SIGINT
# 
echo This is a test script
# 
count=1
while [ $count -le 10 ]
do
    echo "Loop #$count"
    sleep 1
    count=$[ $count + 1 ]
done
#
echo "This is the end of the test script"

$ ./test 
This is a test script
Loop #1
Loop #2
Loop #3
^C Sorry! I have trapped Ctrl-C
Loop #4
Loop #5
Loop #6
^C Sorry! I have trapped Ctrl-C
Loop #7
Loop #8
Loop #9
Loop #10
This is the end of the test script

除了在shell脚本中捕获信号,你也可以在shell脚本退出时进行捕获。这是在shell完成任务时执行命令的一种简便方法。要捕获shell脚本的退出,只要在trap命令后加上EXIT信号就行。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
$ cat test
#!/bin/bash
# Trapping the script exit
# 
trap "echo Goodbye..." EXIT
#
count=1
while [ $count -le 5 ]
do
    echo "Loop #$count"
    sleep 1
    count=$[ $count + 1 ]
done

修改和移除捕获:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# 1. 修改
$ cat test
#!/bin/bash
# Modifying a set trap
#
trap "echo ' Sorry... Ctrl-C is trapped.'" SIGINT
#
count=1
while [ $count -le 5 ]
do
    echo "Loop #$count"
    sleep 1
    count=$[ $count + 1 ]
done
# 
trap "echo ' I modified the trap!'" SIGINT
#
count=1
while [ $count -le 5 ]
do
    echo "Second Loop #$count"
    sleep 1
    count=$[ $count + 1 ]
done

#2. 删除已设置好的捕获,只需要在trap命令与希望默认行为的信号列表之间加上两个破折号就行了。
$ cat test
#!/bin/bash
# Removing a set trap
#
trap "echo ' Sorry... Ctrl-C is trapped'" SIGINT
#
count=1
while [ $count -le 5 ]
do 
    echo "Loop #$count"
    sleep 1
    count=$[ $count + 1 ]
done
#
# Remove the trap
trap -- SIGINT
echo "I just removed the trap"
#
count=1
while [ $count -le 5 ]
do
    echo "Second Loop #$count"
    sleep 1
    count=$[ $count + 1 ]
done

在作业停止后(ctrl+z),linux系统会让你选择是终止还是重启。你可以用kill命令终止该进程。要重启停止的进程需要向其发送一个SIGCONT信号。 启动、停止、终止以及恢复作业的这些功能统称为作业控制。通过作业控制,就能完全控制shell环境中所有进程的运行方式了。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
$ cat test
#!/bin/bash
#
echo "Script Process ID: $$"
#
count=1
while [ $count -le 10 ]
do
    echo "Loop #$count"
    sleep 10
    count=$[ $count + 1 ]
done
#
echo "End of script..."
#

执行上面的脚本,并使用ctrl+z发送stop信号。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
$ ./test 
Script Process ID: 28544
Loop #1
^Z
[1]+  Stopped                 ./test
$ ./test > test.out &
[2] 28546
$ jobs
[1]+  Stopped                 ./test
[2]-  Running                 ./test > test.out &
$ jobs -l
[1]+ 28544 Stopped                 ./test
[2]- 28546 Running                 ./test > test.out &

jobs命令参数

选项 描述
-l 列出进程的PID以及作业号
-n 只列出上次shell发出的通知后改变了状态的作业
-p 只列出作业的PID
-r 只列出运行中的作业
-s 只列出已停止的作业

你可能注意到了jobs命令输出中的加号和减号。带加号的作业会被当做默认作业。在使用作业控制命令时,如果未在命令行指定任何作业号,该作业(带加号的默认作业)会被当成作业控制命令的操作对象。当前的默认作业完成处理后,带减号的作业成为下一个默认作业。任何时候都只有一个带加号的作业和一个带减号的作业,不管shell中有多少个正在运行的作业。

要以后台模式重启一个作业,可用bg命令加上作业号

1
2
3
4
5
6
7
8
dacheg@X450VC:Downloads$ jobs
[1]+  Stopped                 ./test
[2]-  Done                    ./test > test.out
dacheg@X450VC:Downloads$ bg
[1]+ ./test &
Loop #2
dacheg@X450VC:Downloads$ jobs
[1]+  Running                 ./test &

要以前台模式重启一个作业,可用fg命令加上作业号

8. 解压缩和文件归档

① 解压缩数据 linux文件压缩工具

工具 文件扩展名 描述
bzip2 .bz2 采用Burrows-Wheeler块排序文本压缩算法和霍夫曼编码
compress .Z 最初的Unix文件压缩工具,已经快没人用了
gzip .gz GNU压缩工具,用Lempel-Ziv编码, gzip压缩,gzcat查看,gunzip解压
zip .zip Windows上PKZIP工具的Unix实现

② 文件归档 tar命令的格式: tar function [option] object1 object2 ...function参数定义了tar命令应该做什么。

tar命令的function:

功能 长名称 描述
-A –concatenate 将一个已有tar归档文件追加到另一个已有tar归档文件
-c –create 创建一个新的tar归档文件
-d –diff 检查归档文件和文件系统的不同之处
-d –delete 从已有tar归档文件中删除
-r –append 追加文件到已有tar归档文件末尾
-t –list 列出已有tar归档文件的内容
-u –update 将比tar归档文件中已有的同名文件更新的文件追加到该tar归档文件中
-x –extract 从已有tar归档文件中提取文件

tar命令选项

选项 描述
-C dir 切换到指定目录
-f file 指定文件路径
-j 将输出重定向给bzip2命令来压缩内容
-p 保留所有文件权限
-v 在处理文件时显示文件
-z 将输出重定向给gzip命令来压缩内容

9. 文件描述符(file descriptor)

linux系统将每个对象当做文件处理。这包括输入和输出进程。linux用文件描述符(file descriptor)来标识每个文件对象。文件描述符号是一个非负整数,可以唯一标识会话中打开的文件。每个进程一次最多可以有9个文件描述符。出于特殊目的,bash shell保留了前三个文件描述符(0,1和2)。

文件描述符 缩写 描述
0 STDIN 标准输入,对于tty, 标准输入是键盘
1 STDOUT 标准输出, 对于tty,标准输出是终端显示器
2 STDERR 标准错误, 默认和STDOUT指向相同的地方
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 1.同时重定向错误和正常输出
$ ls -al test test2 test3 badtest 2> test6 1>test7
# 将STDERR和STDOUT的输出重定向到同一个输出文件
# 当使用&>时,命令生成的所有输出都会被发送到同一位置。
# &>的后面必须设置一个文件,这个文件可以设置为 /dev/stdout
$ ls -al test test2 test3 badtest &> /dev/stdout

# 2. 永久重定向输出
$ cat test
#!/bin/bash
# redirecting all output to a file
# exec命令会启动一个新shell并将STDOUT文件描述符重定向到文件。脚本中发送给STDOUT的所有输出会被重定向到文件。
exec 1>testout

echo "This is a test of redirecting all output"
echo "from a script to another file"
echo "without having to redirect every individual line"

# 3. 在脚本中重定向输入
$ cat test
#!/bin/bash
# redirecting file input

exec 0< testfile
count=1

while read line
do 
    echo "Line #$count: $line"
    count=$[ $count + 1 ]
done

在脚本中重定向输入和输出时,并不局限于这3个默认的文件描述符。在shell中最多可以有9个打开的文件描述符。其他6个从3~8的文件描述符均可用作输入或输出重定向。你可以将这些文件描述符中的任意一个分配给文件,然后在脚本中使用它们。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# 1. 创建输出文件描述符
$ cat test
#!/bin/bash
# using an alternative file descriptor
# 用exec命令将文件描述符3重定向到另一个文件。
exec 3>test13out
echo "This should display on the monitor"
echo "and this should be stored in the file" >&3
echo "Then this should be back on the monitor"

# 2. 重定向文件描述符
$ cat test
#!/bin/bash
# storing STDOUT, then coming back to it
# exec将文件描述符3重定向到文件描述符1的当前位置,也就是STDOUT。
exec 3>&1
# exec命令将STDOUT重定向到文件。但是文件描述符3仍然指向STDOUT原来的位置,也就是显示器。
exec 1>test14out
echo "This should store in the output file"
echo "along with this line."
exec 1>&3
echo "Now things should be back to normal"

# 3. 创建输入文件描述符
$ cat test15
#!/bin/bash
# redirecting input file description
exec 6<&0
exec 0 < testfile
count=1
while read line
do 
    echo "Line #$count: $line"
    count=$[ $count + 1 ]
done
exec 0<&6
read -p "Are you done now? " answer
case $answer in
Y|y) echo "Goodbye" ;;
N|n) echo "Sorry, this is the end" ;;
esac

# 4. 创建读写文件描述符
# 由于你是对同一个文件进行数据读写,shell会维护一个内部指针,指明在文件中的当前位置。任何读或写都会从文件指针上次的位置开始。
$ cat test
#!/bin/bash
# testing input/output file descriptor
exec 3<> testfile
read file <&3
echo "Read: $line"
echo "This is a test line" >&3
$ cat testfile
This is the first line.
This is the second line.
This is the third line.
# 在运行脚本时,一开始还算正常。输出内容表明脚本读取了testfile文件中的第一行。但如果你在脚本运行结束后,查看testfile文件内容的话,你会发现写入文件中的数据覆盖了已有的数据。
# 当脚本向文件中写入数据时,它会从文件指针处的位置开始。read命令读取了第一行数据,所以它使得文件指针指向了第二行数据的第一个字符。在echo语句将数据输出到文件时,它会将数据放在文件指针的当前位置,覆盖了该位置的已有数据。

# 5. 关闭文件描述符
# 如果你创建了新的输入或输出文件描述符,shell会在脚本退出时自动关闭它们。然而在有些情况下,你需要在脚本结束前手动关闭文件描述符。

lsof命令会列出整个linux系统打开的所有文件描述符。该命令会产生大量的输出。它会显示当前Linux系统上打开的每个文件的有关信息。这包括后台运行的所有进程以及登录到系统的任何用户。有大量的命令行选项和参数可以用来帮助过滤lsof的输出。最常用的有-p和-d,前者允许指定进程ID,后者允许指定要显示的文件描述符编号。-a选项用来对其他两个选项的结果执行布尔AND运算,这会产生如下输出。

1
2
3
4
5
$ lsof -a -p $$ -d 0,1,2
COMMAND   PID   USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
bash    25418 dacheg    0u   CHR  136,3      0t0    6 /dev/pts/3
bash    25418 dacheg    1u   CHR  136,3      0t0    6 /dev/pts/3
bash    25418 dacheg    2u   CHR  136,3      0t0    6 /dev/pts/3

lsof的默认输出

描述
COMMAND 正在运行的命令名的前9个字符
PID 进程的PID
USER 进程属主的登录名
FD 文件描述符号以及访问类型(r代表读,w代表写,u代表读写)
TYPE 文件的类型(CHR代表字符型,BLK代表块型,DIR代表目录,REG代表常规文件)
DEVICE 设备的设备号(主设备号和从设备号)
SIZE 如果有的话,表示文件的大小
NODE 本地文件的节点号
NAME 文件名

10. 调整谦让度

在多任务操作系统中(linux就是),内核负责将CPU时间分配给系统上运行的每个进程。 调整谦让度(scheduling priority)是内核分配给进程的CPU时间(相对于其他进程)。 调度优先级是一个整数值,从-20(最高优先级)到+19(最低优先级)。 默认情况下,bash shell以优先级0来启动所有进程。

使用nice命令来调整调度优先级:

1
2
3
4
5
$ nice -n 10 ./test > test.out &
[1] 4973
$ ps -p 4973 -o pid,ppid,ni,cmd
PID  PPID   NI CMD
4973 4721   10 /bin/bash ./test

注意,只有root用户有权限让命令以更高的优先级运行。 有时,你想改变系统上已运行命令的优先级。这个时候就需要使用renice命令。它允许你指定运行进程的PID来改变它的优先级。

1
2
3
4
5
6
$ ./test &
[1] 5055
$ ps -p 5055 -o pid,ppid,ni,cmd
 PID PPID NI CMD 
 5055 4721 0 /bin/bash ./test11.sh
$ renice -n 10 -p 5055

renice命令会自动更新当前运行进程的调度优先级。和nice命令一样,renice命令也有一些限制:

1
2
3
1. 只能对属于你的进程执行renice;
2. 只能通过renice降低进程的优先级
3. root用户可以通过renice来任意调整进程的优先级。

11. 定时运行作业(cron表)

  1. crontab命令 cron表的格式: min hour dayofmonth month dayofweek command dayofweek可以使用文本值(mon,tue,wed,thu,fri,sat,sun)或数值(0为周日,6为周六)。dayofmonth表项指定月份中的日期值(1~31)。 注意:聪明的读者可能会问如何设置一个在每个月的最后一天执行的命令,因为你无法设置dayofmonth的值来涵盖所有的月份。这个问题困扰着linux和Unix程序员,也激发了不少解决办法。常用的方法是加一条使用date命令的if-then语句来检查明天的日期是不是01:
1
00 12 * * * if [`date +%d -d tomorrow` = 01 ] ; then ; command

command必须是命令的全路径名

  1. cron目录 如果你创建的脚本对精确的执行时间要求不高,用预配置的cron脚本目录会更方便。有4个基本目录:hourly,daily,monthly,weekly。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
dacheg@X450VC:~$ ls /etc/cron.*ly
/etc/cron.daily:
0anacron  apt-compat    cracklib-runtime  google-chrome  man-db   passwd              sysstat                 update-notifier-common
apport    bsdmainutils  dpkg              logrotate      mlocate  popularity-contest  ubuntu-advantage-tools

/etc/cron.hourly:

/etc/cron.monthly:
0anacron

/etc/cron.weekly:
0anacron  man-db  update-notifier-common

因此,如果脚本需要每天运行一次,只要将脚本复制到daily目录,cron就会每天执行它。

  1. anacron程序

crontab程序的唯一问题是它假定linux系统是7*24小时运行的。除非将linux当成服务器环境来运行,否则此假设未必成立。如果某个作业在crontab时间表中安排运行的时间已到,但这个时候linux系统处于关机状态,那么这个作业就不会被运行。当系统开机时,crontab程序不会再去运行那些错过的作业。要解决这个问题,许多linux发行版还包含了anacron程序。

如果anacron知道某个作业错过了执行时间,它会尽快运行该作业。这意味着如果linux系统关机了几天,当它再次开机时,原定在关机期间运行的作业会自动运行。

这个功能常用于进行常规日志维护的脚本。如果系统在脚本应该运行的时间刚好关机,日志文件就不会被整理,可能会变很大。通过anacron,至少可以保证系统每次启动时整理日志文件。

anacron程序只会处理位于cron目录的程序,比如/etc/cron.monthly。它用时间戳来决定作业是否正确的计划间隔内运行了。每个cron目录都有个时间戳文件,该文件位于/var/spool/cron目录下。

anacron程序使用自己的时间表(通常位于/etc/anacrontab)来检查作业目录。

anacron时间表的基本格式和cron时间表略有不同:period delay identifier command。period条目定义了作业多久运行一次,以天为单位。anacron程序用此条目来检查作业的时间戳文件。delay条目会指定系统启动后anacron程序需要等待多少分钟再开始运行错过的脚本。identifier条目是一种特别的非空字符串,如cron-weekly,用于唯一标识日志消息和错误邮件中的作业。command条目包含了run-parts程序和一个cron脚本目录名。run-parts程序负责运行目录中传给它的任何脚本。

注意,anacron不会运行位于/etc/cron.hourly的脚本,因为anacron程序不会处理执行时间需求小于一天的脚本。


本文发表于 0001-01-01,最后修改于 0001-01-01。

本站永久域名「 jiavvc.top 」,也可搜索「 后浪笔记一零二四 」找到我。


上一篇 « 下一篇 »

赞赏支持

请我吃鸡腿 =^_^=

i ysf

云闪付

i wechat

微信

推荐阅读

Big Image