Skip to content

Latest commit

 

History

History
1927 lines (1232 loc) · 58.7 KB

File metadata and controls

1927 lines (1232 loc) · 58.7 KB

十、管理调用

在本章中,我们将涵盖以下主题:

  • 收集有关流程的信息
  • 什么是什么–什么,在哪里,什么是什么,以及文件
  • 杀死进程,发送和响应信号
  • 向用户终端发送消息
  • /proc文件系统
  • 收集系统信息
  • cron调度
  • 数据库样式和用途
  • 写入和读取 SQLite 数据库
  • 从 Bash 中读写 MySQL 数据库
  • 用户管理脚本
  • 批量调整图像大小和格式转换
  • 从终端截图
  • 从一个终端管理多个终端

介绍

从一个 GNU/Linux 生态系统管理多个终端由网络、每组硬件、分配资源的操作系统内核、接口模块、系统实用程序和用户程序组成。管理员需要监控整个系统,以保持一切顺利运行。Linux 管理工具从多合一图形用户界面应用到为脚本设计的命令行工具。

收集有关流程的信息

术语进程在这种情况下是指程序的运行实例。许多进程在一台计算机上同时运行。每个流程都被分配一个唯一的标识号,称为流程标识 ( 工艺流程标识)。具有相同名称的同一个程序的多个实例可以同时运行,但是它们将各自具有不同的 PID 和属性。进程属性包括拥有进程的用户、程序使用的内存量、程序使用的 CPU 时间等。这个食谱展示了如何收集关于过程的信息。

准备好

与流程管理相关的重要命令有toppspgrep。这些工具在所有 Linux 发行版中都可用。

怎么做...

ps报告活动进程的信息。它提供了关于哪个用户拥有进程、进程何时启动、用于执行进程的命令路径、PID、它所连接的终端( TTY 、对于电传)、进程使用的内存、进程使用的 CPU 时间等信息。考虑以下示例:

$ ps
PID TTY       TIME CMD
1220 pts/0    00:00:00 bash
1242 pts/0    00:00:00 ps

默认情况下,ps将显示从当前终端(TTY)启动的进程。第一列显示的是 PID,第二列是终端(TTY),第三列显示的是进程启动后经过了多长时间,最后是 CMD(命令)。

ps命令报告可以用命令行参数修改。

-f (full)选项显示更多的信息列:

$ ps -f
UID        PID  PPID  C STIME TTY          TIME CMD
slynux    1220  1219  0 18:18 pts/0    00:00:00 -bash
slynux    1587  1220  0 18:59 pts/0    00:00:00 ps -f

-e(每)和-ax(所有)选项提供系统上运行的每个进程的报告。

The -x argument (along with -a) specifies the removal of the default TTY restriction imparted by ps. Usually, if you use ps without arguments, it'll only print processes attached to the current terminal.

命令ps -eps -efps -axps -axf生成所有过程的报告,并提供比ps更多的信息:

$ ps -e | head -5
PID TTY    TIME CMD
1 ?        00:00:00 init
2 ?        00:00:00 kthreadd
3 ?        00:00:00 migration/0
4 ?        00:00:00 ksoftirqd/0

-e选项生成长报告。本示例使用head过滤输出,以显示前五个条目。

-o PARAMETER1PARAMETER2选项指定要显示的数据。

Parameters for -o are delimited with a comma (,). There is no space between the comma operator and the next parameter. The -o option can be combined with the -e (every) option (-eo) to list every process running in the system. However, when you use filters similar to the ones that restrict ps to the specified users along with -o, -e is not used. The -e option overrules the filter and displays all the processes.

在本例中,comm代表 COMMAND,pcpu代表 CPU 使用率的百分比:

$ ps -eo comm,pcpu | head -5
COMMAND          %CPU
init             0.0
kthreadd         0.0
migration/0      0.0
ksoftirqd/0      0.0

它是如何工作的...

支持-o选项的以下参数:

| 参数 | 描述 | | pcpu | 中央处理器的百分比 | | pid | 流程标识 | | ppid | 父进程标识 | | pmem | 内存百分比 | | comm | 可执行文件名 | | cmd | 简单的命令 | | user | 启动流程的用户 | | nice | 优先级(精确) | | time | 累计中央处理器时间 | | etime | 自进程启动以来经过的时间 | | tty | 相关的 TTY 装置 | | euid | 有效用户 | | stat | 进程状态 |

还有更多...

可以组合ps命令、grep和其他工具来生成自定义报告。

显示流程的环境变量

一些过程依赖于它们的环境变量定义。了解环境变量和值可以帮助您调试或自定义流程。

ps命令通常不显示命令的环境信息。命令末尾的e输出修改器将此信息添加到输出中:

$ ps e

这里有一个环境信息的例子:

$ ps -eo pid,cmd  e | tail -n 1
1238 -bash USER=slynux LOGNAME=slynux HOME=/home/slynux PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
MAIL=/var/mail/slynux SHELL=/bin/bash SSH_CLIENT=10.211.55.2 49277 22 SSH_CONNECTION=10.211.55.2 49277 10.211.55.4 22 SSH_TTY=/dev/pts/0 

环境信息有助于使用apt-get包管理器跟踪问题。如果使用 HTTP 代理连接互联网,可能需要使用http_proxy=host:port设置环境变量。如果未设置,则apt-get命令将不会选择代理,因此会返回一个错误。知道http_proxy没有设置,问题就明显了。

当调度工具,如cron(本章稍后讨论)用于运行应用时,可能不会设置预期的环境变量。该crontab条目不会打开图形用户界面窗口应用:

00 10 * * * /usr/bin/windowapp

它失败是因为图形用户界面应用需要DISPLAY环境变量。要确定所需的环境变量,请手动运行windowapp,然后运行ps -C windowapp -eo cmd e

确定所需的环境变量后,在crontab中的命令名称前定义它们:

00 10 * * * DISPLAY=:0 /usr/bin/windowapp

运筹学

DISPLAY=0
00 10 * * * /usr/bin/windowapp

定义DISPLAY=:0ps输出中获得。

创建流程的树形视图

ps命令可以报告一个进程 PID,但是从一个子进程到最终父进程的跟踪是繁琐的。将f添加到ps命令的末尾会创建一个流程的树形视图,显示任务之间的父子关系。下一个示例显示了从运行在xterm内部的 bash shell 调用的ssh会话:

$ ps -u clif f | grep -A2 xterm | head -3
15281  ?      S     0:00 xterm 
15284 pts/20  Ss+   0:00 \_ bash
15286 pts/20  S+    0:18 \_ ssh 192.168.1.2

分类 ps 输出

默认情况下,ps命令输出未排序。-sort 参数强制ps对输出进行排序。可以通过在参数中添加+(升序)或-(降序)前缀来指定升序或降序:

$ ps [OPTIONS] --sort -paramter1,+parameter2,parameter3..

例如,要列出消耗 CPU 最多的五个进程,请使用以下内容:

$ ps -eo comm,pcpu --sort -pcpu | head -5
COMMAND         %CPU
Xorg             0.1
hald-addon-stor  0.0
ata/0            0.0
scsi_eh_0        0.0

这将显示前五个进程,按 CPU 使用百分比降序排列。

grep命令可以过滤ps输出。要仅报告当前正在运行的那些 Bash 进程,请使用以下命令:

$ ps -eo comm,pid,pcpu,pmem | grep bash
bash             1255  0.0  0.3
bash             1680  5.5  0.3

带 ps 的过滤器,适用于真实用户或身份证、有效用户或身份证

ps命令可以根据指定的真实有效的用户名或 id 对进程进行分组。ps命令通过检查每个条目是属于参数列表中的特定有效用户还是真实用户来过滤输出。

  • -u EUSER1EUSER2等指定有效用户列表
  • -U RUSER1RUSER2等指定真实用户列表

这里有一个例子:

 # display user and percent cpu usage for processes with real user
 # and effective user of root
 $ ps -u root -U root -o user,pcpu

-o可以和-e一起作为-eo使用,但是当应用过滤器时,不应该使用-e。它会覆盖过滤器选项。

ps 的 TTY 滤波器

ps输出可以通过指定进程所连接的 TTY 来选择。使用-t选项指定 TTY 列表:

 $ ps -t TTY1, TTY2 ..

这里有一个例子:

 $ ps -t pts/0,pts/1
 PID TTY          TIME CMD
 1238 pts/0    00:00:00 bash
 1835 pts/1    00:00:00 bash
 1864 pts/0    00:00:00 ps

关于进程线程的信息

ps-L选项将显示关于进程线程的信息。此选项将 LWP 列添加到线程标识中。将-f选项添加到-L ( -Lf)会添加两列:线程计数 NLWP 和线程标识 LWP:

 $ ps -Lf
 UID  PID  PPID  LWP  C  NLWP  STIME  TTY  TIME     
        CMD
 user 1611 1     1612 0  2     Jan16  ?    00:00:00    
        /usr/lib/gvfs/gvfsd

该命令列出了线程数最多的五个进程:

$ ps -eLf --sort -nlwp | head -5
UID        PID  PPID   LWP  C NLWP STIME TTY  TIME     
     CMD
root       647     1   647  0   64 14:39 ?    00:00:00 
     /usr/sbin/console-kit-daemon --no-daemon
root       647     1   654  0   64 14:39 ?    00:00:00 
     /usr/sbin/console-kit-daemon --no-daemon
root       647     1   656  0   64 14:39 ?    00:00:00 
     /usr/sbin/console-kit-daemon --no-daemon
root       647     1   657  0   64 14:39 ?    00:00:00 
     /usr/sbin/console-kit-daemon --no-daemon

指定要显示的输出宽度和列

ps命令支持许多选项来选择字段,以便显示和控制它们的显示方式。以下是一些更常见的选项:

| -f | 这指定了完整的格式。它包括父 PID 用户标识的开始时间。 | | -u 用户列表 | 这将选择列表中用户拥有的进程。默认情况下,它选择当前用户。 | | -l | 长长的清单。它显示用户标识、父 PID、大小等。 |

什么是什么–什么,在哪里,什么是什么,以及文件

可能有几个同名文件。了解正在调用的可执行文件以及文件是编译代码还是脚本是有用的信息。

怎么做...

whichwhereisfilewhatis命令报告文件和目录的信息。

  • which:哪个命令报告命令的位置:
        $ which ls
 /bin/ls
  • 我们经常在不知道存储可执行文件的目录的情况下使用命令。根据您的PATH变量的定义方式,您可以使用来自/bin/usr/local/bin/opt/PACKAGENAME/bin的命令。
  • 当我们键入命令时,终端会在一组目录中查找该命令,并执行它找到的第一个可执行文件。要搜索的目录在PATH环境变量中指定:
 $ echo $PATH /usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
  • 我们可以添加要搜索的目录并导出新的PATH。要将/opt/bin添加到PATH,请使用以下命令:
        $ export PATH=$PATH:/opt/bin
 # /opt/bin is added to PATH
  • T2 在哪里:whereis类似于哪个命令。它不仅返回命令的路径,还打印手册页的位置(如果可用)和命令源代码的路径(如果可用):
        $ whereis ls
 ls: /bin/ls /usr/share/man/man1/ls.1.gz
  • 什么是:whatis命令输出作为参数给出的命令的单行描述。它从man页面解析信息:
        $ whatis ls
 ls (1)    - list directory contents

file命令报告文件类型。它的语法如下:

        $ file FILENAME
  • 报告的文件类型可能包含几个字或一个长描述:
        $file /etc/passwd
 /etc/passwd: ASCII text
 $ file /bin/ls
 /bin/ls: ELF 32-bit LSB executable, Intel 80386, version 1   
        (SYSV), dynamically linked (uses shared libs), for GNU/Linux    
        2.6.15, stripped

apropos Sometimes we need to search for a command that is related to the topic. The apropos command will search the man pages for a keyword. Here's the code to do this: Apropos topic

从给定的命令名中查找进程标识

假设正在执行一个命令的几个实例。在这样的场景下,我们需要每个进程的 PID。pspgrep命令都返回该信息:

 $ ps -C COMMAND_NAME

或者,返回以下内容:

 $ ps -C COMMAND_NAME -o pid=

=附加到pid时,它从ps的输出中删除表头 PID。要从列中删除标题,请将=附加到参数中。

该命令列出了 Bash 进程的进程标识:

 $ ps -C bash -o pid=
 1255
 1680

pgrep命令还返回一个命令的进程标识列表:

 $ pgrep bash
 1255
 1680

pgrep requires only a portion of the command name as its input argument to extract a Bash command; pgrep ash or pgrep bas will also work, for example. But ps requires you to type the exact command. pgrep supports these output-filtering options.

-d选项指定默认新行以外的输出分隔符:

 $ pgrep COMMAND -d DELIMITER_STRING
 $ pgrep bash -d ":"
 1255:1680

-u选项过滤用户列表:

 $ pgrep -u root,slynux COMMAND

在该命令中,rootslynux是用户。

-c选项返回匹配进程的计数:

 $ pgrep -c COMMAND

确定系统有多忙

系统要么没有使用,要么过载。load average值描述了运行系统的总负荷。它描述了系统上可运行进程的平均数量,即除了中央处理器时间片之外的所有资源的进程。

平均负载由正常运行时间和 top 命令报告。它以三个值报告。第一个值表示 1 分钟内的平均值,第二个值表示 5 分钟内的平均值,第三个值表示 15 分钟内的平均值。

它由正常运行时间报告:

 $ uptime
 12:40:53 up  6:16,  2 users,  load average: 0.00, 0.00, 0.00

最高命令

默认情况下,top命令显示消耗 CPU 最多的进程列表以及基本的系统统计信息,包括进程列表中的任务数量、CPU 内核和内存使用情况。输出每隔几秒钟更新一次。

此命令显示几个参数以及最消耗 CPU 的进程:

    $ top
 top - 18:37:50 up 16 days, 4:41,7 users,load average 0.08 0.05 .11
 Tasks: 395 total,  2 running, 393 sleeping, 0 stopped 0 zombie

请参见...

  • 本章中的用 cron 配方安排说明了如何安排任务

杀死进程,发送和响应信号

如果您需要降低系统负载,或者在重新启动之前,您可能需要终止进程(如果它们变得混乱并开始消耗太多资源)。信号是一种进程间通信机制,它会中断正在运行的进程,并迫使它执行某些操作。这些操作包括强制进程以受控或立即的方式终止。

准备好

信号向正在运行的程序发送中断。当一个进程接收到一个信号时,它通过执行一个信号处理程序来响应。编译后的应用通过kill系统调用产生信号。可以使用kill命令从命令行(或 shell 脚本)生成信号。trap命令可以在脚本中用来处理接收到的信号。

每个信号由一个名称和一个整数值标识。SIGKILL (9)信号立即终止一个过程。击键事件 Ctrl + CCtrl + Z 发送信号中止任务或将任务放到后台。

怎么做...

  1. 终止-l命令将列出可用信号:
        $ kill -l
 SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
 ...
  1. 终止流程:
        $ kill PROCESS_ID_LIST

kill命令默认发出SIGTERM信号。进程标识列表以空格作为分隔符。

  1. -s选项指定要发送到流程的信号:
        $ kill -s SIGNAL PID

SIGNAL参数是信号名称或信号编号。有许多信号可用于不同的目的。最常见的如下:

  • SIGHUP 1:控制进程或终端死亡时的挂断检测

  • SIGINT 2:这是按下 Ctrl + C 时发出的信号

  • SIGKILL 9:这是用来强行杀进程的信号

  • SIGTERM 15:这是默认情况下用来终止进程的信号

  • SIGTSTP 20:这是按下 Ctrl + Z 时发出的信号

  1. 我们经常对进程使用强制终止。小心使用。这是一个即时操作,它不会保存数据或执行正常的清理操作。先尝试SIGTERM信号;SIGKILL应保存为极端措施:
        $ kill -s SIGKILL PROCESS_ID

或者,使用它来执行清理操作:

        $ kill -9 PROCESS_ID

还有更多...

Linux 支持其他命令来发出信号或终止进程。

杀戮家族的命令

kill命令以进程标识为参数。killall命令通过名称终止进程:

    $ killall process_name

-s选项指定要发送的信号。默认情况下,killall发送SIGTERM信号:

    $ killall -s SIGNAL process_name

-9选项通过名称强制终止进程:

    $ killall -9 process_name

这是前面的一个例子:

    $ killall -9 gedit

-u所有者指定流程的用户:

    $ killall -u USERNAME process_name

-I选项使killall run处于交互模式:

pkill命令类似于kill命令,但默认情况下,它接受进程名称而不是进程标识:

    $ pkill process_name
 $ pkill -s SIGNAL process_name

SIGNAL为信号编号。pkill不支持SIGNAL名称。pkill命令提供了许多与kill命令相同的选项。查看pkill手册页了解更多详情。

捕捉和响应信号

表现良好的程序保存数据,并在收到SIGTERM信号时干净地关闭。trap命令为脚本中的信号分配一个信号处理器。一旦使用trap命令将一个功能分配给一个信号,当脚本接收到一个信号时,该功能就被执行。

语法如下:

    trap 'signal_handler_function_name' SIGNAL LIST

SIGNAL LIST用空格分隔。它可以包括信号编号和信号名称。

这个 shell 脚本响应SIGINT信号:

#/bin/bash 
#Filename: sighandle.sh 
#Description: Signal handler  

function handler() 
{ 
  echo Hey, received signal : SIGINT 
} 

# $$ is a special variable that returns process ID of current  
# process/script 

echo My process ID is $$ 

#handler is the name of the signal handler function for SIGINT signal 
trap 'handler' SIGINT 

while true; 
do 
  sleep 1 
done 

在终端中运行这个脚本。当脚本运行时,按下 Ctrl + C 将通过执行与之关联的信号处理程序来显示消息。 Ctrl + C 对应一个SIGINT信号。

while循环用于保持进程永远运行而不被终止。这样做是为了让脚本能够响应信号。保持一个过程无限活跃的循环通常被称为事件循环

如果给出了脚本的进程 ID,kill命令可以向其发送信号:

    $ kill -s SIGINT PROCESS_ID

执行前一个脚本时,将打印该脚本的进程标识;或者,您可以使用ps命令找到它。

如果没有为信号指定信号处理程序,脚本将调用操作系统分配的默认信号处理程序。一般按下 Ctrl + C 会终止一个程序,因为操作系统提供的默认处理程序会终止进程。这里定义的自定义处理程序覆盖默认处理程序。

我们可以使用trap命令为任何可用信号(kill -l)定义信号处理程序。一个信号处理器可以处理多个信号。

向用户终端发送消息

Linux 支持三个应用在另一个用户的屏幕上显示消息。write命令向用户发送消息,talk命令让两个用户对话,wall命令向所有用户发送消息。

在做一些有潜在破坏性的事情(比如重启服务器)之前,系统管理员应该向系统或网络上每个用户的终端发送一条消息。

准备好

writewall命令是大多数 Linux 发行版的一部分。如果用户多次登录,您可能需要指定您希望向其发送消息的终端。

您可以使用who命令确定用户的终端:

    $> who
 user1    pts/0    2017-01-16 13:56 (:0.0)
 user1    pts/1    2017-01-17 08:35 (:0.0)

第二列(pts/#)是用户的终端标识。

writewall程序在单个系统上工作。talk程序可以通过网络连接用户。

talk 程序通常不安装。通话程序和通话服务器都必须安装并运行在任何使用通话的机器上。在基于 Debian 的系统上以talktalkd的形式安装 talk 应用,或者在基于红帽的系统上以talktalk-server的形式安装 talk 应用。您可能需要编辑/etc/xinet.d/talk/etc/xinet.d/ntalk来将disable字段设置为no。完成后,重启xinet:

    # cd /etc/xinet.d
 # vi ntalk
 # cd /etc/init.d
 #./xinetd restart

怎么做...

向一个用户发送一条消息

write 命令将向单个用户发送一条消息:

    $ write USERNAME [device]

您可以从文件或回显中重定向消息,也可以交互写入。交互式写入以 Ctrl-D 结束

可以通过将伪终端标识符附加到命令来将消息定向到特定会话:

    $ echo "Log off now. I'm rebooting the system" | write user1 pts/3

与另一个用户保持对话

talk 命令打开两个用户之间的交互式对话。这个的语法是$ talk user@host

下一个命令启动与用户 2 在工作站上的对话:

    $ talk user2@workstation2.example.com

键入通话命令后,您的终端会话将被清除并分成两个窗口。在其中一个窗口中,您将看到如下文本:

    [Waiting for your party to respond]

您试图与之交谈的人会看到这样的信息:

    Message from Talk_Daemon@workstation1.example.com
 talk: connection requested by user1@workstation.example.com
 talk: respond with talk user1@workstation1.example.com

当他们调用 talk 时,他们的终端会话也将被清除和分割。您键入的内容将出现在他们屏幕上的一个窗口中,他们键入的内容将出现在您的屏幕上:

    I need to reboot the database server.
 How much longer will your processing take?
 ---------------------------------------------
 90% complete. Should be just a couple more minutes.

向所有用户发送消息

wall(writell)命令向所有用户和终端会话广播一条消息:

    $ cat message | wall

或者:

    $ wall < message
 Broadcast Message from slynux@slynux-laptop
 (/dev/pts/1) at 12:54 ...

 This is a message

消息头显示谁发送了消息:哪个用户和哪个主机。

写、说和墙命令仅在启用写消息选项时在用户之间传递消息。无论写消息选项如何,都会显示来自根的消息。

通常会启用消息选项。mesg命令将启用或禁用消息接收:

    # enable receiving messages
 $ mesg y
 # disable receiving messages
 $ mesg n

/proc 文件系统

/proc是一个内存中的伪文件系统,为用户提供了对 Linux 内核内部数据结构的空间访问。大多数伪文件都是只读的,但有些文件,如/proc/sys/net/ipv4/forward(在第八章老男孩网络中描述的),可以用来微调您系统的行为。

怎么做...

/proc目录包含多个文件和目录。您可以使用catlessmore查看/proc及其子目录中的大多数文件。它们显示为纯文本。

系统上运行的每个进程在/proc中都有一个目录,根据进程的 PID 命名。

假设 Bash 运行的是 PID4295(pgrep bash);在这种情况下,/proc/4295就会存在。该文件夹将包含有关该过程的信息。/proc/PID下的文件包括:

  • environ:包含与流程相关的环境变量。cat /proc/4295/environ将显示传递给流程的环境变量4295
  • cwd:这是流程工作目录的symlink
  • exe:这是对流程可执行文件的symlink:
        $ readlink /proc/4295/exe
 /bin/bash
  • fd:这是由进程使用的文件描述符的条目组成的目录。值 0、1 和 2 分别是 stdin、stdout 和 stderr。
  • io:该文件显示进程读取或写入的字符数。

收集系统信息

描述一个计算机系统需要许多数据集。这些数据包括网络信息、主机名、内核版本、Linux 发行版名称、CPU 描述、内存分配、磁盘分区等。可以从命令行检索这些信息。

怎么做...

  1. hostnameuname命令打印当前系统的主机名:
        $ hostname

或者,他们打印以下内容:

        $ uname -n
 server.example.com
  1. uname-a选项打印关于 Linux 内核版本、硬件架构等的详细信息:
        $ uname -a
 server.example.com 2.6.32-642.11.1.e16.x86_64 #1 SMP Fri Nov 18   
        19:25:05 UTC 2016 x86_64 x86_64 GNU/Linux
  1. -r选项将报告限制在内核版本:
        $ uname -r
 2.6.32-642.11.1.e16.x86_64
  1. -m选项打印机器类型:
        $ uname -m
 x86_64
  1. /proc/目录保存关于系统、模块和运行进程的信息。/proc/cpuinfo包含 CPU 详细信息:
        $ cat /proc/cpuinfo
 processor     : 0
 vendor_id     : GenuineIntel
 cpu family    : 6
 model         : 63
 model name    : Intel(R)Core(TM)i7-5820K CPU @ 3.30GHz
 ...

如果处理器有多个内核,这些线将重复 n 次。要仅提取一项信息,请使用sed。第五行包含处理器名称:

        $ cat /proc/cpuinfo | sed -n 5p
 Intel(R)CORE(TM)i7-5820K CPU @ 3.3 GHz
  1. /proc/meminfo包含有关内存和当前内存使用情况的信息:
        $ cat /proc/meminfo
 MemTotal:     32777552 kB
 MemFree:      11895296 kB 
 Buffers:        634628 kB
 ...

meminfo第一行显示系统总内存:

        $ cat /proc/meminfo  | head -1
 MemTotal:        1026096 kB
  1. /proc/partitions描述磁盘分区:
        $ cat /proc/partitions
 major minor  #blocks  name
 8        0 976762584 sda
 8        1    512000 sda1
 8        2 976248832 sda2
 ...

fdisk程序编辑磁盘的分区表,并报告当前的分区表。作为root运行该命令:

        $ sudo fdisk -l
  1. lshwdmidecode应用生成关于您的系统的长而完整的报告。该报告包括有关主板、基本输入输出系统、中央处理器、内存插槽、接口插槽、磁盘等的信息。这些必须以 root 用户身份运行。dmidecode是常用的,但是你可能需要安装lshw:
        $ sudo lshw
 description: Computer
 product: 440BX
 vendor: Intel
 ...

 $ sudo dmidecode
 SMBIOS 2.8 present
 115 structures occupying 4160 bytes.
 Table at 0xDCEE1000.

 BIOS Information
 Vendor: American Megatrends Inc
 ...

与 cron 一起计划

GNU/Linux 系统支持几种调度任务的实用程序。cron效用是最广泛支持的。它允许您定期安排任务在后台运行。cron实用程序使用一个表(crontab),其中包含要执行的脚本或命令的列表以及它们的执行时间。

Cron 用于安排系统内务处理任务,例如执行备份、将系统时钟与ntpdate同步以及删除临时文件。

普通用户可以使用cron来安排互联网下载在深夜进行,此时他们的互联网服务提供商允许下载上限,并且可用带宽较高。

准备好

所有 GNU/Linux 发行版都附带了cron调度实用程序。它扫描cron表以确定命令是否要运行。每个用户都有自己的cron表,这是一个纯文本文件。crontab命令操纵cron表。

怎么做...

crontab条目指定执行命令的时间和要执行的命令。cron表中的每一行定义一个命令。该命令可以是脚本或二进制应用。当cron运行一个任务时,它作为创建条目的用户运行,但是它并不来源于用户的.bashrc。如果任务需要环境变量,它们必须在crontab中定义。

每个 cron 表行由六个空格分隔的字段组成,顺序如下:

  • Minute (0 - 59)
  • Hour (0 - 23)
  • Day (1 - 31)
  • Month (1 - 12)
  • Weekday (0 - 6)
  • COMMAND(要在指定时间执行的脚本或命令)

前五个字段指定执行命令实例的时间。多个值由逗号分隔(没有空格)。一颗星表示任何时间或任何一天都匹配。一个分割标志安排事件触发每/Y 间隔 (/5* 以分钟为单位表示每五分钟一次)。

  1. 在所有日期所有时间的第 2分钟执行test.sh脚本:
        02 * * * * /home/slynux/test.sh
  1. 在所有日期的第 5 个、第 6 个和第 7 个小时执行测试。
        00 5,6,7 * * /home/slynux/test.sh
  1. 周日每隔一小时执行script.sh:
        00 */2 * * 0 /home/slynux/script.sh
  1. 每天凌晨 2 点关闭电脑:
        00 02 * * * /sbin/shutdown -h
  1. crontab命令可以交互使用,也可以与预先写好的文件一起使用。

使用带有crontab-e选项编辑cron表格:

        $ crontab -e
 02 02 * * * /home/slynux/script.sh

当输入crontab -e时,默认文本编辑器(通常为vi)打开,用户可以输入cron作业并保存。cron作业将按指定的时间间隔进行调度和执行。

  1. 可以从脚本中调用crontab命令,用新的 crontab 替换当前的 crontab。你是这样做的:
    • 创建一个包含cron作业的文本文件(例如task.cron,然后使用该文件名作为命令参数运行crontab:
                $ crontab task.cron
  • 或者,将cron作业指定为内联函数,而不创建单独的文件。例如,请参考以下内容:
                $ crontab<<EOF
 02 * * * * /home/slynux/script.sh
 EOF

cron作业需要写在crontab<<EOFEOF之间。

它是如何工作的...

星号(*)指定在给定的时间段内,应该在每个实例上执行该命令。在cron作业的Hour字段中的*将导致每小时执行一次命令。要在一个时间段的多个实例上执行该命令,请在该时间字段中指定用逗号分隔的时间间隔。例如,要在第 5分钟和第 10分钟运行命令,请在Minute字段中输入5,10。斜线(除以)符号将导致命令按照时间分割运行。例如,“分钟”字段中的 0-30/6 将在每小时的前半部分每 5 分钟运行一次命令。小时字段中的字符串*/12将每隔一小时运行一个命令。

Cron 作业作为创建crontab的用户执行。如果需要执行需要更高权限的命令,如关闭计算机,以 root 用户身份运行crontab命令。

cron 作业中指定的命令用命令的完整路径写入。这是因为 cron 并不是你的.bashrc的来源,所以执行 cron 作业的环境与我们在终端上执行的 bash shell 是不同的。因此,PATH环境变量可能没有设置。如果您的命令需要某些环境变量,则必须显式设置它们。

还有更多...

crontab命令有更多选项。

指定环境变量

许多命令需要正确设置环境变量才能执行。cron 命令将 SHELL 变量设置为"/bin/sh ",并且还从/etc/passwd中的值设置LOGNAMEHOME。如果需要其他变量,可以在crontab中定义。这些可以为所有任务定义,也可以为单个任务单独定义。

如果定义了MAILTO环境变量,cron将通过电子邮件向该用户发送命令输出。

crontab通过在用户的cron表中插入一行变量赋值语句来定义环境变量。

下面的crontab定义了一个http_proxy环境变量,使用代理服务器进行互联网交互:

    http_proxy=http://192.168.0.3:3128
 MAILTO=user@example.com
 00 * * * * /home/slynux/download.sh

这种格式受到vixie-cron的支持,用于 Debian、Ubunto 和 CentOS 发行版。对于其他发行版,可以根据每个命令定义环境变量:

    00 * * * * http_proxy=http:192.168.0.2:3128;   
    /home/sylinux/download.sh

在系统启动时运行命令

在系统启动(或引导)时运行特定命令是常见的要求。一些cron实现支持@reboot时间字段,以便在重启过程中运行作业。请注意,并非所有的cron实现都支持该功能,并且在某些系统上只允许 root 用户使用该功能。现在查看以下代码:

    @reboot command

这将在运行时以用户身份运行命令。

查看 cron 表

crontab 的-l选项将列出当前用户的 crontab:

    $ crontab -l
 02 05 * * * /home/user/disklog.sh

添加-u选项将指定用户的 crontab 进行查看。您必须以超级用户身份登录才能使用-u选项:

    # crontab -l -u slynux
 09 10 * * * /home/slynux/test.sh

正在删除 cron 表

-r选项将删除当前用户的 cron 表:

    $ crontab -r

-u选项指定要删除的 crontab。您必须是根用户才能删除其他用户的 crontab:

    # crontab -u slynux -r

数据库样式和用途

Linux 支持多种风格的数据库,从简单的文本文件(/etc/passwd)到低级别的 B-Tree 数据库(Berkely DB 和 bdb)、轻量级 SQL(SQL lite)以及功能齐全的关系数据库服务器,如 Postgres、Oracle 和 MySQL。

选择数据库样式的一个经验法则是使用对您的应用来说最简单的系统。当字段已知且固定时,一个文本文件和grep对于一个小数据库就足够了。

有些应用需要参考。例如,图书和作者的数据库应该创建两个表,一个用于图书,一个用于作者,以避免每本书的作者信息重复。

如果表被读取的次数比被修改的次数多,那么 SQLite 是一个不错的选择。这个数据库引擎不需要服务器,这使得它可以移植并很容易嵌入到另一个应用中(就像火狐一样)。

如果数据库经常被多个任务修改(例如,一个网络商店的库存系统),那么其中一个关系数据库管理系统(如 Postgres、Oracle 或 MySQL)是合适的。

准备好

您可以使用标准 Shell 工具创建基于文本的数据库。默认情况下通常安装 SqlLite 可执行文件为sqlite3。您需要安装 MySQL、Oracle 和 Postgres。下一节将解释如何安装 MySQL。你可以从 www.oracle.com 下载甲骨文。Postgres 通常可以通过您的包管理器获得。

怎么做...

文本文件数据库可以用常用的 shell 工具来构建。

要创建地址列表,请创建一个文件,每个地址一行,字段用已知字符分隔。在这种情况下,字符是波浪号(~):

    first last~Street~City, State~Country~Phone~

例如:

    Joe User~123 Example Street~AnyTown, District~1-123-123-1234~

然后添加一个函数来查找匹配模式的行,并将每一行翻译成人性化的格式:

    function  addr {
 grep $1 $HOME/etc/addr.txt | sed 's/~/\n/g'
 }

使用时,类似于以下内容:

    $ addr Joe
 Joe User
 123 Example Street 
 AnyTown District
 1-123-123-1234

还有更多...

SQLite、Postgres、Oracle 和 MySQL 数据库应用提供了一种更强大的数据库范例,称为关系数据库。关系数据库存储表之间的关系,例如,一本书和它的作者之间的关系。

与关系数据库交互的一种常见方式是使用 SQL。SQLite、Postgres、Oracle、MySQL 和其他数据库引擎都支持这种语言。

SQL 是一种丰富的语言。你可以读专门关于它的书。幸运的是,您只需要几个命令就可以有效地使用 SQL。

创建表格

表格由CREATE TABLE命令定义:

 CREATE TABLE tablename (field1 type1, field2 type2,...); 

下一行创建一个图书和作者表:

 CREATE TABLE book (title STRING, author STRING); 

将行插入到 SQL 数据库中

insert 命令将向数据库中插入一行数据。

 INSERT INTO table (columns) VALUES (val1, val2,...); 

以下命令插入您当前正在阅读的书籍:

 INSERT INTO book (title, author) VALUES ('Linux Shell Scripting 
 Cookbook', 'Clif Flynt'); 

从 SQL 数据库中选择行

select 命令将选择与测试匹配的所有行:

 SELECT fields FROM table WHERE test; 

该命令将从图书表中选择包含单词“Shell”的图书标题:

 SELECT title FROM book WHERE title like '%Shell%'; 

写入和读取 SQLite 数据库

SQLite 是一个轻量级数据库引擎,用于从安卓应用和火狐到美国海军库存系统的应用。由于使用范围广,运行 SQLite 的应用比任何其他数据库都多。

SQLite 数据库是由一个或多个数据库引擎访问的单个文件。数据库引擎是一个可以链接到应用的 C 库;它作为一个库被加载到脚本语言中,如 TCL、Python 或 Perl,或者作为一个独立的程序运行。

独立应用 sqlite3 最容易在 shell 脚本中使用。

准备好了

您的安装中可能没有安装sqlite3可执行文件。如果不是,可以用你的包管理器加载sqlite3包进行安装。

对于 Debian 和 Ubuntu,使用以下内容:

    apt-get install sqlite3 libsqlite3-dev

对于红帽、SuSE、软呢帽和 Centos,请使用以下选项:

    yum install sqlite sqlite-devel

怎么做...

sqlite3命令是一个连接到 SQLite 数据库的交互式数据库引擎,支持创建表、插入数据、查询表等过程。

sqlite3命令的语法是这样的:

    sqlite3 databaseName

如果databaseName文件存在,sqlite3将打开它。如果文件不存在,sqlite3将创建一个空数据库。在这个配方中,我们将创建一个表,插入一行,并检索该条目:

    # Create a books database
 $ sqlite3 books.db
 sqlite> CREATE TABLE books (title string, author string);
 sqlite> INSERT INTO books (title, author) VALUES ('Linux Shell      
    Scripting Cookbook', 'Clif Flynt');
 sqlite> SELECT * FROM books WHERE author LIKE '%Flynt%';
 Linux Shell Scripting Cookbook|Clif Flynt

它是如何工作的...

sqlite3应用创建一个名为books.db的空数据库,并显示sqlite> prompt来接受 SQL 命令。

CREATE TABLE命令创建一个包含两个字段的表格:标题和作者。

INSERT命令将一本书插入数据库。SQL 中的字符串用单引号分隔。

SELECT命令检索与测试匹配的行。百分比符号(%)是 SQL 通配符,类似于 Shell 中的星号(*)。

还有更多...

shell 脚本可以使用sqlite3访问数据库,并提供简单的用户界面。下一个脚本用sqlite而不是平面文本文件来实现上一个地址数据库。它提供了三个命令:

  • init:这是创建数据库
  • insert:这是新增一行
  • query:这是选择匹配查询的行

在使用中,它看起来像这样:

    $> dbaddr.sh init
 $> dbaddr.sh insert 'Joe User' '123-1234' 'user@example.com'
 $> dbaddr.sh query name Joe
 Joe User
 123-1234
 user@example.com

以下脚本实现了这个数据库应用:

    #!/bin/bash
    # Create a command based on the first argument

    case $1 in
      init )
        cmd="CREATE TABLE address \
          (name string, phone string, email string);" ;;
      query )
        cmd="SELECT name, phone, email FROM address \
          WHERE $2 LIKE '$3';";;
      insert )
        cmd="INSERT INTO address (name, phone, email) \
          VALUES ( '$2', '$3', '$4' );";;
    esac

    # Send the command to sqlite3 and reformat the output

    echo $cmd | sqlite3 $HOME/addr.db | sed 's/|/\n/g'

该脚本使用 case 语句来选择 SQL 命令字符串。其他命令行参数用该字符串替换,该字符串被发送到sqlite3进行计算。$1$2$3$4分别是剧本的第一、第二、第三和第四个论点。

从 Bash 中读写 MySQL 数据库

MySQL 是一个广泛使用的数据库管理系统。2009 年,甲骨文收购了 SUN,并以此收购了 MySQL 数据库。马里亚数据库包是独立于甲骨文的 MySQL 包的一个分支。MariaDB 可以访问 MySQL 数据库,但是 MySQL 引擎不能总是访问 MariaDB 数据库。

MySQL 和 MariaDB 都有许多语言的接口,包括 PHP、Python、C++、Tcl 等等。他们都使用mysql命令来提供一个交互会话,以便访问数据库。这是 shell 脚本与 MySQL 数据库交互的最简单方式。这些例子应该适用于 MySQL 或 MariaDB。

bash 脚本可以将文本或逗号分隔值 ( CSV )文件转换为 MySQL 表和行。例如,我们可以通过运行 shell 脚本中的查询来读取留言簿程序数据库中存储的所有电子邮件地址。

下一组脚本演示了如何将文件的内容插入到学生的数据库表中,并生成报告,同时对系内的每个学生进行排名。

准备好

MySQL 和 MariaDB 并不总是出现在基本的 Linux 发行版中。它们既可以作为mysql-servermysql-client安装,也可以作为mariadb-server套装安装。MariaDB 发行版使用 MySQL 作为命令,有时在请求 MySQL 包时安装。

MySQL 支持用户名和密码进行身份验证。安装过程中会提示您输入密码。

使用mysql命令在全新安装上创建新数据库。使用CREATE DATABASE命令创建数据库后,可以选择它与 use 命令一起使用。选择数据库后,可以使用标准的 SQL 命令来创建表和插入数据:

$> mysql -user=root -password=PASSWORD

Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 44
Server version: 10.0.29-MariaDB-0+deb8u1 (Debian)

Copyright (c) 2000, 2016, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> CREATE DATABASE test1;
Query OK, 1 row affected (0.00 sec)
MariaDB [(none)]> use test1;

quit命令或 Ctrl-D 将终止mysql交互会话。

怎么做...

这个食谱由三个脚本组成:一个创建数据库和表格,一个插入学生数据,一个从表格中读取和显示数据。

创建数据库和表脚本:

#!/bin/bash 
#Filename: create_db.sh 
#Description: Create MySQL database and table 

USER="user" 
PASS="user" 

mysql -u $USER -p$PASS <<EOF 2> /dev/null 
CREATE DATABASE students; 
EOF 

[ $? -eq 0 ] && echo Created DB || echo DB already exist  
mysql -u $USER -p$PASS students <<EOF 2> /dev/null 
CREATE TABLE students( 
id int, 
name varchar(100), 
mark int, 
dept varchar(4) 
); 
EOF 

[ $? -eq 0 ] && echo Created table students || \
    echo Table students already exist  

mysql -u $USER -p$PASS students <<EOF 
DELETE FROM students; 
EOF 

该脚本在表中插入数据:

#!/bin/bash 
#Filename: write_to_db.sh 
#Description: Read from CSV and write to MySQLdb 

USER="user" 
PASS="user" 

if [ $# -ne 1 ]; 
then 
  echo $0 DATAFILE 
  echo 
  exit 2 
fi 

data=$1 

while read line; 
do 

  oldIFS=$IFS 
  IFS=, 
  values=($line) 
  values[1]="\"`echo ${values[1]} | tr ' ' '#' `\"" 
  values[3]="\"`echo ${values[3]}`\"" 

  query=`echo ${values[@]} | tr ' #' ', ' ` 
  IFS=$oldIFS 

  mysql -u $USER -p$PASS students <<EOF 
INSERT INTO students VALUES($query); 
EOF 

done< $data 
echo Wrote data into DB 

最后一个脚本查询数据库并生成报告:

#!/bin/bash 
#Filename: read_db.sh 
#Description: Read from the database 

USER="user" 
PASS="user" 

depts=`mysql -u $USER -p$PASS students <<EOF | tail -n +2 
SELECT DISTINCT dept FROM students; 
EOF` 

for d in $depts; 
do 

echo Department : $d 

result="`mysql -u $USER -p$PASS students <<EOF 
SET @i:=0; 
SELECT @i:=@i+1 as rank,name,mark FROM students WHERE dept="$d" ORDER BY mark DESC; 
EOF`" 

echo "$result" 
echo 

done 

输入 CSV 文件(studentdata.csv)的数据如下所示:

1,Navin M,98,CS
2,Kavya N,70,CS
3,Nawaz O,80,CS
4,Hari S,80,EC
5,Alex M,50,EC
6,Neenu J,70,EC
7,Bob A,30,EC
8,Anu M,90,AE
9,Sruthi,89,AE
10,Andrew,89,AE

按照以下顺序执行脚本:

$ ./create_db.sh 
Created DB
Created table students

$ ./write_to_db.sh studentdat.csv
Wrote data into DB

$ ./read_db.sh 
Department : CS
rank  name  mark
1  Navin M  98
2  Nawaz O  80
3  Kavya N  70

Department : EC
rank  name  mark
1  Hari S  80
2  Neenu J 70
3  Alex M  50
4  Bob A   30

Department : AE
rank  name  mark
1  Anu M    90
2  Sruthi   89
3  Andrew   89

它是如何工作的...

第一个脚本create_db.sh创建了一个名为students的数据库和一个名为students的表。mysql命令用于 MySQL 操作。mysql命令用-u指定用户名,用-pPASSWORD指定密码。变量USERPASS用于存储用户名和密码。

mysql命令的另一个命令参数是数据库名称。如果数据库名称被指定为mysql命令的参数,它将使用该数据库;否则,我们必须使用 database_name命令明确定义要使用的数据库。

mysql命令通过标准输入(stdin)接受要执行的查询。通过stdin供应多条线路的一种便捷方式是使用<<EOF方法。出现在<<EOFEOF之间的文本作为标准输入传递到mysql

CREATE DATABASECREATE TABLE命令将stderr重定向到/dev/null以防止显示错误信息。该脚本检查存储在$?中的mysql命令的退出状态,以确定是否发生了故障;它假设失败是因为表或数据库已经存在。如果数据库或表已经存在,将显示一条消息通知用户;否则,将创建数据库和表。

write_to_db.sh脚本接受学生数据 CSV 文件的文件名。它在while循环中读取 CSV 文件的每一行。在每次迭代中,CSV 文件中的一行被读取并重新格式化为一个 SQL 命令。该脚本将逗号分隔行中的数据存储在数组中。数组赋值以这种形式完成:array=(val1 val2 val3)。这里的空格字符是内部 字段 分隔符 ( IFS )。该数据有逗号分隔的值。通过将 IFS 更改为逗号,我们可以轻松地为数组赋值(IFS=,)。

逗号分隔行中的数据元素是idnamemarkdepartmentidmark值是整数,namedept是必须引用的字符串。

该名称可能包含与国际单项体育联合会冲突的空格字符。脚本用字符(#)替换名称中的空格,并在制定查询后恢复它。

要引用字符串,数组中的值用前缀重新分配,并以\"作为后缀。tr命令将名称中的每个空格替换为#

最后用逗号代替空格字符,用空格代替#形成查询。然后,执行 SQL 的INSERT命令。

第三个脚本read_db.sh,为每个系生成一个按排名排序的学生列表。第一个查询查找不同的部门名称。我们使用while循环遍历每个部门,并运行查询以获得最高分的顺序显示学生详细信息。SET @i=0是一个 SQL 构造,用来设置:i=0。在每一行中,它都会递增并显示为学生的等级。

用户管理脚本

GNU/Linux 是一个多用户操作系统,允许许多用户同时登录和执行活动。涉及用户管理的管理任务包括设置用户的默认 Shell、向组中添加用户、禁用 Shell 帐户、添加新用户、删除用户、设置密码、设置用户帐户的到期日期等。这个配方展示了一个用户管理工具来处理这些任务。

怎么做...

该脚本执行常见的用户管理任务:

#!/bin/bash 
#Filename: user_adm.sh 
#Description: A user administration tool 

function usage() 
{ 
  echo Usage: 
  echo Add a new user 
  echo $0 -adduser username password 
  echo 
  echo Remove an existing user 
  echo $0 -deluser username 
  echo 
  echo Set the default shell for the user 
  echo $0 -shell username SHELL_PATH 
  echo 
  echo Suspend a user account 
  echo $0 -disable username 
  echo 
  echo Enable a suspended user account 
  echo $0 -enable username 
  echo 
  echo Set expiry date for user account 
  echo $0 -expiry DATE  
  echo 
  echo Change password for user account 
  echo $0 -passwd username 
  echo 
  echo Create a new user group 
  echo $0 -newgroup groupname 
  echo 
  echo Remove an existing user group 
  echo $0 -delgroup groupname 
  echo 
  echo Add a user to a group 
  echo $0 -addgroup username groupname 
  echo 
  echo Show details about a user 
  echo $0 -details username 
  echo 
  echo Show usage 
  echo $0 -usage 
  echo 

  exit 
} 

if [ $UID -ne 0 ]; 
then 
  echo Run $0 as root. 
  exit 2 
fi 

case $1 in 

  -adduser) [ $# -ne 3 ] && usage ; useradd $2 -p $3 -m ;;  
  -deluser) [ $# -ne 2 ] && usage ; deluser $2 --remove-all-files;; 
  -shell)    [ $# -ne 3 ] && usage ; chsh $2 -s $3 ;; 
  -disable) [ $# -ne 2 ] && usage ; usermod -L $2 ;;  
  -enable) [ $# -ne 2 ] && usage ; usermod -U $2  ;; 
  -expiry) [ $# -ne 3 ] && usage ; chage $2 -E $3 ;; 
  -passwd) [ $# -ne 2 ] && usage ; passwd $2 ;; 
  -newgroup) [ $# -ne 2 ] && usage ; addgroup $2 ;; 
  -delgroup) [ $# -ne 2 ] && usage ; delgroup $2 ;; 
  -addgroup) [ $# -ne 3 ] && usage ; addgroup $2 $3 ;; 
  -details) [ $# -ne 2 ] && usage ; finger $2 ; chage -l $2 ;; 
  -usage) usage ;; 
  *) usage ;; 
esac 

示例输出如下所示:

# ./user_adm.sh -details test
Login: test                 Name: 
Directory: /home/test                 Shell: /bin/sh
Last login Tue Dec 21 00:07 (IST) on pts/1 from localhost
No mail.
No Plan.
Last password change          : Dec 20, 2010
Password expires          : never
Password inactive         : never
Account expires             : Oct 10, 2010
Minimum number of days between password change    : 0
Maximum number of days between password change    : 99999
Number of days of warning before password expires  : 7

它是如何工作的...

user_adm.sh脚本执行几个常见的用户管理任务。usage()文本解释了当用户提供不正确的参数或包含-usage参数时如何使用脚本。case 语句解析命令参数并执行适当的命令。

user_adm.sh脚本的有效命令选项有:-adduser-deluser-shell-disable-enable-expiry-passwd-newgroup-delgroup-addgroup-details-usage。当*)情况匹配时,表示没有选项被识别;因此,调用usage()

以 root 用户身份运行此脚本。它在检查参数之前确认用户标识(根的用户标识是0)。

当一个参数匹配时,[ $# -ne 3 ] &&测试用法检查参数的数量。如果命令参数的数量与要求的数量不匹配,则调用usage()函数并退出脚本。

以下脚本支持这些选项:

  • -useradd:useradd命令创建一个新用户:
        useradd USER -p PASSWORD -m
  • -m选项创建主目录。
  • -deluser:deluser命令删除用户:
        deluser USER --remove-all-files
  • --remove-all-files选项删除所有与用户相关的文件,包括home目录。
  • -shell:chsh命令改变用户的默认 Shell:
        chsh USER -s SHELL
  • -disable-enable:usermod命令操作与用户账户相关的几个属性。usermod -L USER锁定用户账户,usermod -U USER解锁用户账户。
  • -expiry:change命令操作用户账户到期信息:
        chage -E DATE

支持以下选项:

  • -m MIN_DAYS:将密码更改的最小间隔天数设置为MIN_DAYS

  • -passwd:passwd命令更改用户密码:

        passwd USER

该命令将提示输入新密码:

  • -newgroup-addgroup:addgroup命令向系统添加新的用户组:
        addgroup GROUP

如果您包含用户名,它会将此用户添加到组中:

        addgroup USER GROUP
 -delgroup

delgroup命令删除一个用户组:

        delgroup GROUP
  • -details:finger USER命令显示用户信息,包括主目录、上次登录时间、默认 shell 等。chage -l命令显示用户账户到期信息。

批量调整图像大小和格式转换

我们都从手机和相机下载照片。在我们通过电子邮件发送图像或将其发布到网站之前,我们可能需要调整其大小或更改其格式。我们可以使用脚本批量修改这些图像文件。本食谱描述了图像管理的食谱。

准备好了

来自 ImageMagick 套件的convert命令包含用于操作图像的工具。它支持许多图像格式和转换选项。大多数 GNU/Linux 发行版默认情况下不包含 ImageMagick。您需要手动安装软件包。欲了解更多信息,请将您的网络浏览器指向www.imagemagick.org

怎么做...

转换程序会将文件从一种图像格式转换为另一种图像格式:

    $ convert INPUT_FILE OUTPUT_FILE

这里有一个例子:

    $ convert file1.jpg file1.png

我们可以通过指定比例百分比或输出图像的宽度和高度来调整图像的大小。要通过指定WIDTHHEIGHT来调整图像大小,请使用以下命令:

    $ convert imageOrig.png -resize WIDTHxHEIGHT imageResized.png

这里有一个例子:

    $ convert photo.png -resize 1024x768 wallpaper.png

如果WIDTHHEIGHT缺失,那么将自动计算缺失的部分,以保持图像纵横比:

    $ convert image.png -resize WIDTHx image.png

这里有一个例子:

    $ convert image.png -resize 1024x image.png

要通过指定百分比比例因子来调整图像大小,请使用以下命令:

    $ convert image.png -resize "50%" image.png

该脚本将对目录中的所有映像执行一组操作:

#!/bin/bash 
#Filename: image_help.sh 
#Description: A script for image management 

if [ $# -ne 4 -a $# -ne 6 -a $# -ne 8 ]; 
then 
  echo Incorrect number of arguments 
  exit 2 
fi 

while [ $# -ne 0 ]; 
do 

  case $1 in 
  -source) shift; source_dir=$1 ; shift ;; 
  -scale) shift; scale=$1 ; shift ;; 
  -percent) shift; percent=$1 ; shift ;; 
  -dest) shift ; dest_dir=$1 ; shift ;; 
  -ext) shift ; ext=$1 ; shift ;; 
  *) echo Wrong parameters; exit 2 ;; 
  esac; 

done 

for img in `echo $source_dir/*` ; 
do 
  source_file=$img 
  if [[ -n $ext ]]; 
  then 
    dest_file=${img%.*}.$ext 
  else 
    dest_file=$img 
  fi 

  if [[ -n $dest_dir ]]; 
  then 
    dest_file=${dest_file##*/} 
    dest_file="$dest_dir/$dest_file" 
  fi 

  if [[ -n $scale ]]; 
  then 
    PARAM="-resize $scale" 
  elif [[ -n $percent ]];   then 
    PARAM="-resize $percent%"  
  fi 

  echo Processing file : $source_file 
  convert $source_file $PARAM $dest_file 

done 

以下示例将sample_dir目录中的图像缩放至20%:

$ ./image_help.sh -source sample_dir -percent 20%
Processing file :sample/IMG_4455.JPG
Processing file :sample/IMG_4456.JPG
Processing file :sample/IMG_4457.JPG
Processing file :sample/IMG_4458.JPG

要将图像缩放到1024的宽度,请使用以下命令:

$ ./image_help.sh -source sample_dir -scale 1024x

要将文件缩放并转换到指定的目标目录,请使用以下命令:

# newdir is the new destination directory
$ ./image_help.sh -source sample -scale 50% -ext png -dest newdir

它是如何工作的...

前面的image_help.sh脚本接受这些参数:

  • -source:指定图像的源目录。
  • -dest:指定转换后的图像文件的目标目录。如果未指定-dest,目标目录将与源目录相同。
  • -ext:指定转换的目标文件格式。
  • -percent:指定缩放百分比。
  • -scale:指定缩放后的宽度和高度。
  • -percent-scale参数可能都不会出现。
  • 该脚本首先检查命令参数的数量。四个、六个或八个参数都有效。

命令行通过while循环进行解析,case 语句和值被分配给适当的变量。$#是一个包含参数个数的特殊变量。shift命令将命令参数向左移动一个位置。这样,每次换档时,我们可以将下一个命令参数作为$1访问,而不是使用$1$2$3等等。

case 语句就像 C 编程语言中的 switch 语句。当匹配一个案例时,执行相应的语句。每个匹配语句以;;结束。一旦所有参数被解析成变量percentscalesource_dirextdest_dir,则for循环遍历源文件目录中的每个文件,并转换该文件。

for循环中进行几个测试来微调转换。

如果定义了变量ext(如果在命令参数中给出了-ext,目标文件的扩展名将从source_file.extension更改为source_file.$ext

如果提供了-dest参数,则通过用目标目录替换源路径中的目录来修改目标文件路径。

如果指定了-比例或-百分比,则调整大小参数(-resize widthx-resize perc%)会添加到命令中。

评估参数后,使用适当的参数执行convert命令。

请参见

  • 第二章中的基于扩展名的切片文件名解释了如何提取文件名的一部分

从终端截图

随着图形用户界面应用的激增,截屏变得非常重要,既可以记录您的操作,也可以报告意想不到的结果。Linux 支持几种截图工具。

准备好了

本节将描述 xwd 应用和 ImageMagick 中的一个工具,该工具在之前的配方中使用过。xwd 应用通常与基本图形用户界面一起安装。您可以使用软件包管理器安装 ImageMagick。

怎么做...

xwd 程序从窗口中提取视觉信息,将其转换为 X Window Dump 格式,并将数据打印到stdout。该输出可以被重定向到一个文件,并且该文件可以被转换成 GIF、PNG 或 JPEG 格式,如前面的配方所示。

当 xwd 被调用时,它会将你的光标变成十字准线。当你将十字准线移动到一个 X 窗口并点击它时,窗口被抓取:

    $ xwd >step1.xwd

ImageMagick 的import命令支持更多截图选项:

要截图整个屏幕,请使用以下命令:

    $ import -window root screenshot.png

您可以手动选择一个区域,并使用以下命令截图:

    $ import screenshot.png

要拍摄特定窗口的屏幕截图,请使用以下命令:

    $ import -window window_id screenshot.png

xwininfo命令将返回一个窗口标识。运行该命令,然后单击所需的窗口。然后,将此window_id值传递给import-window选项。

从一个终端管理多个终端

SSH 会话、Konsoles 和 xterms 是您想要长时间运行的应用的重量级解决方案,但是它们很少执行检查(例如监控日志文件或磁盘使用情况)。

GNU 屏幕实用程序在终端会话中创建多个虚拟屏幕。当屏幕隐藏时,您在虚拟屏幕中启动的任务会继续运行。

准备好

为此,我们将使用名为 GNU 屏幕的实用程序。如果默认情况下屏幕没有安装在您的发行版上,请使用软件包管理器进行安装:

    apt-get install screen

怎么做...

  1. 一旦屏幕实用程序创建了一个新窗口,所有的击键都指向该窗口中运行的任务,除了控制-A ( Ctrl - A ,这标志着屏幕命令的开始。

  2. 创建屏幕窗口:要创建新屏幕,请从 shell 运行命令屏幕。您将看到一条欢迎消息,其中包含有关屏幕的信息。按空格键或回车返回 Shell 提示。要创建新的虚拟终端,请按 Ctrl + A ,然后按 C (这些区分大小写)或再次键入屏幕。

  3. 查看打开窗口列表:运行屏幕时,按下 Ctrl + A 后跟一个引号(")将列出您的终端会话。

  4. 窗口间切换:击键 Ctrl + ACtrl + N 显示下一个窗口, Ctrl + ACtrl + P 显示上一个窗口。

  5. 连接和分离屏幕:屏幕命令支持保存和加载屏幕会话,在屏幕术语中称为分离和连接。要退出当前屏幕会话,请按 Ctrl + ACtrl + D 。要在启动屏幕时附加到现有屏幕,请使用:

        screen -r -d
  1. 这告诉屏幕附加最后一个屏幕会话。如果您有多个分离的会话,屏幕将输出一个列表;然后使用:
        screen -r -d PID

这里,PID是要附加的屏幕会话的 PID。