在本章中,我们将涵盖以下主题:
- 收集有关流程的信息
- 什么是什么–什么,在哪里,什么是什么,以及文件
- 杀死进程,发送和响应信号
- 向用户终端发送消息
/proc
文件系统- 收集系统信息
- 用
cron
调度 - 数据库样式和用途
- 写入和读取 SQLite 数据库
- 从 Bash 中读写 MySQL 数据库
- 用户管理脚本
- 批量调整图像大小和格式转换
- 从终端截图
- 从一个终端管理多个终端
从一个 GNU/Linux 生态系统管理多个终端由网络、每组硬件、分配资源的操作系统内核、接口模块、系统实用程序和用户程序组成。管理员需要监控整个系统,以保持一切顺利运行。Linux 管理工具从多合一图形用户界面应用到为脚本设计的命令行工具。
术语进程在这种情况下是指程序的运行实例。许多进程在一台计算机上同时运行。每个流程都被分配一个唯一的标识号,称为流程标识 ( 工艺流程标识)。具有相同名称的同一个程序的多个实例可以同时运行,但是它们将各自具有不同的 PID 和属性。进程属性包括拥有进程的用户、程序使用的内存量、程序使用的 CPU 时间等。这个食谱展示了如何收集关于过程的信息。
与流程管理相关的重要命令有top
、ps
、pgrep
。这些工具在所有 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 -e
、ps -ef
、ps -ax
和ps -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 PARAMETER1
、PARAMETER2
选项指定要显示的数据。
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=:0
从ps
输出中获得。
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
命令输出未排序。-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
命令可以根据指定的真实有效的用户名或 id 对进程进行分组。ps
命令通过检查每个条目是属于参数列表中的特定有效用户还是真实用户来过滤输出。
- 用
-u EUSER1
、EUSER2
等指定有效用户列表 - 用
-U RUSER1
、RUSER2
等指定真实用户列表
这里有一个例子:
# 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 来选择。使用-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、大小等。 |
可能有几个同名文件。了解正在调用的可执行文件以及文件是编译代码还是脚本是有用的信息。
which
、whereis
、file
和whatis
命令报告文件和目录的信息。
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。ps
和pgrep
命令都返回该信息:
$ 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
在该命令中,root
和slynux
是用户。
-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 + C 、 Ctrl + Z 发送信号中止任务或将任务放到后台。
- 终止
-l
命令将列出可用信号:
$ kill -l
SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
...
- 终止流程:
$ kill PROCESS_ID_LIST
kill
命令默认发出SIGTERM
信号。进程标识列表以空格作为分隔符。
-s
选项指定要发送到流程的信号:
$ kill -s SIGNAL PID
SIGNAL
参数是信号名称或信号编号。有许多信号可用于不同的目的。最常见的如下:
-
SIGHUP 1
:控制进程或终端死亡时的挂断检测 -
SIGINT 2
:这是按下 Ctrl + C 时发出的信号 -
SIGKILL 9
:这是用来强行杀进程的信号 -
SIGTERM 15
:这是默认情况下用来终止进程的信号 -
SIGTSTP 20
:这是按下 Ctrl + Z 时发出的信号
- 我们经常对进程使用强制终止。小心使用。这是一个即时操作,它不会保存数据或执行正常的清理操作。先尝试
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
命令向所有用户发送消息。
在做一些有潜在破坏性的事情(比如重启服务器)之前,系统管理员应该向系统或网络上每个用户的终端发送一条消息。
write
和wall
命令是大多数 Linux 发行版的一部分。如果用户多次登录,您可能需要指定您希望向其发送消息的终端。
您可以使用who
命令确定用户的终端:
$> who
user1 pts/0 2017-01-16 13:56 (:0.0)
user1 pts/1 2017-01-17 08:35 (:0.0)
第二列(pts/#
)是用户的终端标识。
write
和wall
程序在单个系统上工作。talk
程序可以通过网络连接用户。
talk 程序通常不安装。通话程序和通话服务器都必须安装并运行在任何使用通话的机器上。在基于 Debian 的系统上以talk
和talkd
的形式安装 talk 应用,或者在基于红帽的系统上以talk
和talk-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
是一个内存中的伪文件系统,为用户提供了对 Linux 内核内部数据结构的空间访问。大多数伪文件都是只读的,但有些文件,如/proc/sys/net/ipv4/forward
(在第八章、老男孩网络中描述的),可以用来微调您系统的行为。
/proc
目录包含多个文件和目录。您可以使用cat
、less
或more
查看/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 描述、内存分配、磁盘分区等。可以从命令行检索这些信息。
hostname
和uname
命令打印当前系统的主机名:
$ hostname
或者,他们打印以下内容:
$ uname -n
server.example.com
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
-r
选项将报告限制在内核版本:
$ uname -r
2.6.32-642.11.1.e16.x86_64
-m
选项打印机器类型:
$ uname -m
x86_64
/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
/proc/meminfo
包含有关内存和当前内存使用情况的信息:
$ cat /proc/meminfo
MemTotal: 32777552 kB
MemFree: 11895296 kB
Buffers: 634628 kB
...
meminfo
第一行显示系统总内存:
$ cat /proc/meminfo | head -1
MemTotal: 1026096 kB
/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
lshw
和dmidecode
应用生成关于您的系统的长而完整的报告。该报告包括有关主板、基本输入输出系统、中央处理器、内存插槽、接口插槽、磁盘等的信息。这些必须以 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
...
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* 以分钟为单位表示每五分钟一次)。
- 在所有日期所有时间的第 2分钟执行
test.sh
脚本:
02 * * * * /home/slynux/test.sh
- 在所有日期的第 5 个、第 6 个和第 7 个小时执行测试。
00 5,6,7 * * /home/slynux/test.sh
- 周日每隔一小时执行
script.sh
:
00 */2 * * 0 /home/slynux/script.sh
- 每天凌晨 2 点关闭电脑:
00 02 * * * /sbin/shutdown -h
crontab
命令可以交互使用,也可以与预先写好的文件一起使用。
使用带有crontab
的-e
选项编辑cron
表格:
$ crontab -e
02 02 * * * /home/slynux/script.sh
当输入crontab -e
时,默认文本编辑器(通常为vi
)打开,用户可以输入cron
作业并保存。cron
作业将按指定的时间间隔进行调度和执行。
- 可以从脚本中调用
crontab
命令,用新的 crontab 替换当前的 crontab。你是这样做的:- 创建一个包含
cron
作业的文本文件(例如task.cron
,然后使用该文件名作为命令参数运行crontab
:
- 创建一个包含
$ crontab task.cron
- 或者,将
cron
作业指定为内联函数,而不创建单独的文件。例如,请参考以下内容:
$ crontab<<EOF
02 * * * * /home/slynux/script.sh
EOF
cron
作业需要写在crontab<<EOF
和EOF
之间。
星号(*
)指定在给定的时间段内,应该在每个实例上执行该命令。在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
中的值设置LOGNAME
和HOME
。如果需要其他变量,可以在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
这将在运行时以用户身份运行命令。
crontab 的-l
选项将列出当前用户的 crontab:
$ crontab -l
02 05 * * * /home/user/disklog.sh
添加-u
选项将指定用户的 crontab 进行查看。您必须以超级用户身份登录才能使用-u
选项:
# crontab -l -u slynux
09 10 * * * /home/slynux/test.sh
-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);
insert 命令将向数据库中插入一行数据。
INSERT INTO table (columns) VALUES (val1, val2,...);
以下命令插入您当前正在阅读的书籍:
INSERT INTO book (title, author) VALUES ('Linux Shell Scripting
Cookbook', 'Clif Flynt');
select 命令将选择与测试匹配的所有行:
SELECT fields FROM table WHERE test;
该命令将从图书表中选择包含单词“Shell”的图书标题:
SELECT title FROM book WHERE title like '%Shell%';
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
分别是剧本的第一、第二、第三和第四个论点。
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-server
和mysql-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
指定密码。变量USER
和PASS
用于存储用户名和密码。
mysql
命令的另一个命令参数是数据库名称。如果数据库名称被指定为mysql
命令的参数,它将使用该数据库;否则,我们必须使用 database_name
命令明确定义要使用的数据库。
mysql
命令通过标准输入(stdin
)接受要执行的查询。通过stdin
供应多条线路的一种便捷方式是使用<<EOF
方法。出现在<<EOF
和EOF
之间的文本作为标准输入传递到mysql
。
CREATE DATABASE
和CREATE TABLE
命令将stderr
重定向到/dev/null
以防止显示错误信息。该脚本检查存储在$?
中的mysql
命令的退出状态,以确定是否发生了故障;它假设失败是因为表或数据库已经存在。如果数据库或表已经存在,将显示一条消息通知用户;否则,将创建数据库和表。
write_to_db.sh
脚本接受学生数据 CSV 文件的文件名。它在while
循环中读取 CSV 文件的每一行。在每次迭代中,CSV 文件中的一行被读取并重新格式化为一个 SQL 命令。该脚本将逗号分隔行中的数据存储在数组中。数组赋值以这种形式完成:array=(val1 val2 val3)
。这里的空格字符是内部 字段 分隔符 ( IFS )。该数据有逗号分隔的值。通过将 IFS 更改为逗号,我们可以轻松地为数组赋值(IFS=,
)。
逗号分隔行中的数据元素是id
、name
、mark
和department
。id
和mark
值是整数,name
和dept
是必须引用的字符串。
该名称可能包含与国际单项体育联合会冲突的空格字符。脚本用字符(#
)替换名称中的空格,并在制定查询后恢复它。
要引用字符串,数组中的值用前缀重新分配,并以\"
作为后缀。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
我们可以通过指定比例百分比或输出图像的宽度和高度来调整图像的大小。要通过指定WIDTH
或HEIGHT
来调整图像大小,请使用以下命令:
$ convert imageOrig.png -resize WIDTHxHEIGHT imageResized.png
这里有一个例子:
$ convert photo.png -resize 1024x768 wallpaper.png
如果WIDTH
或HEIGHT
缺失,那么将自动计算缺失的部分,以保持图像纵横比:
$ 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 语句。当匹配一个案例时,执行相应的语句。每个匹配语句以;;
结束。一旦所有参数被解析成变量percent
、scale
、source_dir
、ext
和dest_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
-
一旦屏幕实用程序创建了一个新窗口,所有的击键都指向该窗口中运行的任务,除了控制-A ( Ctrl - A ,这标志着屏幕命令的开始。
-
创建屏幕窗口:要创建新屏幕,请从 shell 运行命令屏幕。您将看到一条欢迎消息,其中包含有关屏幕的信息。按空格键或回车返回 Shell 提示。要创建新的虚拟终端,请按 Ctrl + A ,然后按 C (这些区分大小写)或再次键入屏幕。
-
查看打开窗口列表:运行屏幕时,按下 Ctrl + A 后跟一个引号(
"
)将列出您的终端会话。 -
窗口间切换:击键 Ctrl + A 和 Ctrl + N 显示下一个窗口, Ctrl + A 和 Ctrl + P 显示上一个窗口。
-
连接和分离屏幕:屏幕命令支持保存和加载屏幕会话,在屏幕术语中称为分离和连接。要退出当前屏幕会话,请按 Ctrl + A 和 Ctrl + D 。要在启动屏幕时附加到现有屏幕,请使用:
screen -r -d
- 这告诉屏幕附加最后一个屏幕会话。如果您有多个分离的会话,屏幕将输出一个列表;然后使用:
screen -r -d PID
这里,PID
是要附加的屏幕会话的 PID。