实用脚本创作与有趣小脚本开发
1. 高级脚本功能概述
在编写 shell 脚本时,有一些高级功能可以帮助我们实现更多复杂的任务。下面将介绍三个重要的高级功能:使用 MySQL 服务器存储数据、使用 lynx 浏览器提取网页数据以及使用 Mailx 程序发送报告。
-
使用 MySQL 服务器存储数据
- 首先,为应用程序在 MySQL 中创建一个数据库和唯一的用户账户,并仅授予该用户账户对该数据库的权限。
- 然后,创建表来存储应用程序使用的数据。
-
最后,使用
mysql命令行工具与 MySQL 服务器进行交互,提交SELECT查询并检索结果进行显示。
-
使用 lynx 浏览器提取网页数据
-
lynx是一个基于文本的浏览器,可以将网页上的所有文本转储出来。 - 利用标准的 shell 编程技能来存储这些数据,并搜索所需的内容。
-
-
使用 Mailx 程序发送报告
- Mailx 程序允许我们使用 Linux 系统上安装的电子邮件服务器轻松地将命令输出发送到任何电子邮件地址。
2. 有趣小脚本:发送消息
学习编写 bash shell 脚本的主要目的是创建自己的 Linux 系统实用工具。不过,有时候编写一些有趣的脚本也有助于巩固脚本编写的概念。下面将详细介绍一个用于在 Linux 系统上向其他用户发送消息的脚本。
2.1 所需功能理解
这个简单的脚本只需要几个功能,部分命令是常见的,而有些可能不太熟悉。下面将介绍所需的命令。
-
确定系统上的用户
使用who命令可以查看当前登录到系统的所有用户。示例如下:
bash $ who christine tty2 2015-09-10 11:43 timothy tty3 2015-09-10 11:46 [...] $
默认情况下,who命令提供简短的信息,与who -s命令输出相同,包含以下内容:- 用户姓名
- 用户的终端
- 用户登录系统的时间
发送消息时,只需要前两项信息,即用户名和用户当前的终端。
-
允许消息接收
用户可以使用mesg实用程序禁止任何人向他们发送消息。因此,在尝试发送消息之前,最好检查消息是否被允许。-
检查自己的消息状态:
bash $ mesg is n $
结果is n表示消息功能已关闭,如果结果为is y,则表示允许接收消息。 - 不同 Linux 发行版的默认设置不同,例如 Ubuntu 默认关闭消息功能,而 CentOS 默认开启。
-
检查其他用户的消息状态:
bash $ who -T christine - tty2 2015-09-10 12:56 timothy - tty3 2015-09-10 11:46 [...] $
用户名后面的短横线-表示该用户关闭了消息功能,加号+表示允许接收消息。 -
开启自己的消息接收功能:
bash $ whoami christine $ $ mesg y $ $ mesg is y $
通过执行mesg y命令,用户christine开启了消息接收功能。
-
检查自己的消息状态:
-
向其他用户发送消息
该脚本的主要工具是write命令。只要消息功能被允许,write命令就可以使用用户名和当前终端向另一个登录用户发送消息。需要注意的是,write命令只能向虚拟控制台终端登录的用户成功发送消息,登录到图形环境的用户无法接收消息。示例:从用户
christine向登录在tty3终端的用户timothy发送消息:
bash $ who christine tty2 2015-09-10 13:54 timothy tty3 2015-09-10 11:46 [...] $ $ write timothy tty3 Hello Tim! $
执行write命令后,会出现一个空行,用于输入消息文本。可以输入多行消息,按Enter键换行,输入完成后按Ctrl+D组合键发送整个消息。接收者看到的消息如下:
Message from christine@server01 on tty2 at 14:11 ... Hello Tim! EOF
接收者可以看到发送消息的用户和终端,以及时间戳。消息底部的EOF表示文件结束,让接收者知道整个消息已显示完毕。通常,接收者收到消息后需要按Enter键才能再次显示提示符。
3. 创建脚本
使用脚本发送消息可以克服一些潜在的问题,例如在系统中有大量用户时,查找要发送消息的用户会很麻烦,并且需要确定该用户是否允许接收消息。脚本可以加快这个过程,让我们轻松地向特定用户发送消息。
3.1 检查用户是否登录
通过在脚本执行时传递一个参数来指定要发送消息的用户。使用以下脚本代码来确定该用户是否登录:
# Determine if user is logged on:
#
logged_on=$(who | grep -i -m 1 $1 | gawk '{print $1}')
#
if [ -z $logged_on ]
then
echo "$1 is not logged on."
echo "Exiting script..."
exit
fi
#
在上述代码中,
who
命令的结果通过管道传递给
grep
命令,
grep
命令使用
-i
选项忽略大小写,
-m 1
选项确保只匹配第一个结果。如果用户未登录,
grep
命令将不产生输出;如果用户登录,将输出用户名的第一个登录信息。这个输出再传递给
gawk
命令,
gawk
命令只返回第一个项目,即用户名或空字符串。最终结果存储在
logged_on
变量中。
如果
logged_on
变量为空字符串,表示用户未登录,脚本将输出相应信息并退出;如果用户登录,脚本将继续执行。
示例:传递用户名
Charlie
作为参数,该用户当前未登录:
$ ./mu.sh Charlie
Charlie is not logged on.
Exiting script...
$
3.2 检查用户是否允许接收消息
使用以下脚本代码来确定登录用户是否允许接收消息:
# Determine if user allows messaging:
#
allowed=$(who -T | grep -i -m 1 $1 | gawk '{print $2}')
#
if [ $allowed != "+" ]
then
echo "$1 does not allowing messaging."
echo "Exiting script..."
exit
fi
#
这里使用
who -T
命令和选项来显示用户的消息状态。结果通过管道传递给
grep
和
gawk
命令,提取消息指示符并存储在
allowed
变量中。如果
allowed
变量的值不是
+
,表示用户不允许接收消息,脚本将输出相应信息并退出;否则,脚本将继续执行。
示例:用户
Samantha
当前已登录但关闭了消息功能:
$ ./mu.sh Samantha
Samantha does not allowing messaging.
Exiting script...
$
3.3 检查是否包含消息
消息作为脚本的第二个参数传递,因此需要检查是否包含消息参数。使用以下脚本代码:
# Determine if a message was included:
#
if [ -z $2 ]
then
echo "No message parameter included."
echo "Exiting script..."
exit
fi
#
如果第二个参数为空字符串,表示没有包含消息,脚本将输出相应信息并退出。
示例:传递用户名
Timothy
但未包含消息:
$ ./mu.sh Timothy
No message parameter included.
Exiting script...
$
3.4 发送简单消息
在发送消息之前,需要确定用户的当前终端并存储在变量中。使用以下脚本代码:
# Send message to user:
#
uterminal=$(who | grep -i -m 1 $1 | gawk '{print $2}')
#
echo $2 | write $logged_on $uterminal
#
who
、
grep
和
gawk
命令再次用于确定用户的当前终端,并存储在
uterminal
变量中。使用
echo
命令将消息发送到标准输出,然后通过管道传递给
write
命令,
logged_on
变量保存用户名,
uterminal
变量保存用户的当前终端。
示例:向用户
Timothy
发送简单消息
test
:
$ ./mu.sh Timothy test
$
用户
Timothy
在其终端上收到的消息如下:
Message from christine@server01 on tty2 at 10:23 ...
test
EOF
3.5 发送长消息
当需要发送包含多个单词的长消息时,原脚本会出现问题,因为 bash shell 将空格视为参数分隔符。可以使用
shift
命令和
while
循环来解决这个问题。
# Determine if there is more to the message:
#
shift
#
while [ -n "$1" ]
do
whole_message=$whole_message' '$1
shift
done
#
shift
命令允许我们处理脚本参数,将下一个参数移动到
$1
位置。在
while
循环中,不断将每个消息单词添加到
whole_message
变量中,直到处理完所有参数。
修改脚本以发送
whole_message
变量:
# Send message to user:
#
uterminal=$(who | grep -i -m 1 $1 | gawk '{print $2}')
#
echo $whole_message | write $logged_on $uterminal
#
但是,使用
shift
命令会移除
$1
参数的内容,导致脚本在使用
$1
时产生错误。可以使用一个变量
muser
来保存
$1
参数的值:
# Save the username parameter
#
muser=$1
#
然后将脚本中所有的
$1
替换为
muser
:
# Determine if user is logged on:
#
logged_on=$(who | grep -i -m 1 $muser | gawk '{print $1}')
#
if [ -z $logged_on ]
then
echo "$muser is not logged on."
echo "Exiting script..."
exit
fi
#
# Determine if user allows messaging:
#
allowed=$(who -T | grep -i -m 1 $muser | gawk '{print $2}')
#
if [ $allowed != "+" ]
then
echo "$muser does not allowing messaging."
echo "Exiting script..."
exit
fi
#
# Determine if a message was included:
#
if [ -z $2 ]
then
echo "No message parameter included."
echo "Exiting script..."
exit
fi
#
# Determine if there is more to the message:
#
shift
#
while [ -n "$1" ]
do
whole_message=$whole_message' '$1
shift
done
#
# Send message to user:
#
uterminal=$(who | grep -i -m 1 $muser | gawk '{print $2}')
#
echo $whole_message | write $logged_on $uterminal
#
exit
示例:向用户
Timothy
发送长消息
The boss is coming! Look busy!
:
$ ./mu.sh Timothy The boss is coming! Look busy!
$
用户
Timothy
在其终端上收到的消息如下:
Message from christine@server01 on tty2 at 10:30 ...
The boss is coming! Look busy!
EOF
4. 脚本改进建议
以下是一些可以尝试的脚本改进建议:
- 不将用户名和消息作为参数传递,而是使用选项。
- 如果用户登录到多个终端,允许向这些多个终端发送消息。(提示:使用多个
write
命令。)
- 如果要发送的消息是给当前仅登录到 GUI 的用户,向脚本用户输出消息并退出脚本。(记住
write
命令只能向虚拟控制台终端写入消息。)
- 允许将存储在文件中的长消息发送到终端。(提示:使用
cat
命令的输出通过管道传递给
write
实用程序,而不是
echo
命令。)
下面是整个消息脚本的流程图:
graph TD;
A[开始] --> B[检查用户是否登录];
B -- 用户未登录 --> C[输出提示信息并退出];
B -- 用户已登录 --> D[检查用户是否允许接收消息];
D -- 用户不允许 --> E[输出提示信息并退出];
D -- 用户允许 --> F[检查是否包含消息];
F -- 未包含消息 --> G[输出提示信息并退出];
F -- 包含消息 --> H[处理长消息];
H --> I[确定用户终端];
I --> J[发送消息];
J --> K[结束];
通过以上步骤,我们可以创建一个简单而有趣的脚本,用于在 Linux 系统上向其他用户发送消息。同时,还可以根据自己的需求对脚本进行改进和扩展。
实用脚本创作与有趣小脚本开发
5. 操作步骤总结
为了更清晰地展示创建发送消息脚本的过程,下面将整个流程总结为详细的操作步骤:
1.
确定系统上的用户
:使用
who
命令查看当前登录系统的所有用户,获取用户名和终端信息。
2.
检查消息接收权限
:使用
mesg
命令检查自己的消息接收状态,使用
who -T
命令检查其他用户的消息接收状态。若要开启消息接收,使用
mesg y
命令。
3.
测试发送消息
:使用
write
命令向已登录且允许接收消息的用户发送消息,按
Ctrl+D
组合键完成消息发送。
4.
创建脚本
:
-
检查用户是否登录
:使用
who | grep -i -m 1 $1 | gawk '{print $1}'
确定用户是否登录。
-
检查用户是否允许接收消息
:使用
who -T | grep -i -m 1 $1 | gawk '{print $2}'
检查用户消息接收权限。
-
检查是否包含消息
:检查第二个参数是否为空。
-
发送简单消息
:确定用户当前终端,使用
echo $2 | write $logged_on $uterminal
发送消息。
-
处理长消息
:使用
shift
命令和
while
循环处理长消息,将消息存储在
whole_message
变量中。
-
修正脚本错误
:使用
muser
变量保存用户名,替换脚本中的
$1
。
6. 代码示例总结
下面将创建消息发送脚本的完整代码示例再次给出,方便参考:
#!/bin/bash
#
#mu.sh - Send a Message to a particular user
#############################################
#
# Save the username parameter
#
muser=$1
#
# Determine if user is logged on:
#
logged_on=$(who | grep -i -m 1 $muser | gawk '{print $1}')
#
if [ -z $logged_on ]
then
echo "$muser is not logged on."
echo "Exiting script..."
exit
fi
#
# Determine if user allows messaging:
#
allowed=$(who -T | grep -i -m 1 $muser | gawk '{print $2}')
#
if [ $allowed != "+" ]
then
echo "$muser does not allowing messaging."
echo "Exiting script..."
exit
fi
#
# Determine if a message was included:
#
if [ -z $2 ]
then
echo "No message parameter included."
echo "Exiting script..."
exit
fi
#
# Determine if there is more to the message:
#
shift
#
while [ -n "$1" ]
do
whole_message=$whole_message' '$1
shift
done
#
# Send message to user:
#
uterminal=$(who | grep -i -m 1 $muser | gawk '{print $2}')
#
echo $whole_message | write $logged_on $uterminal
#
exit
7. 脚本改进详细分析
7.1 使用选项替代参数
目前脚本是通过参数传递用户名和消息,可使用选项来提高脚本的灵活性。例如,使用
-u
选项指定用户名,
-m
选项指定消息。以下是修改后的示例代码:
#!/bin/bash
#
#mu.sh - Send a Message to a particular user
#############################################
while getopts "u:m:" opt; do
case $opt in
u)
muser=$OPTARG
;;
m)
message=$OPTARG
;;
\?)
echo "Invalid option: -$OPTARG" >&2
exit 1
;;
:)
echo "Option -$OPTARG requires an argument." >&2
exit 1
;;
esac
done
# Determine if user is logged on:
#
logged_on=$(who | grep -i -m 1 $muser | gawk '{print $1}')
#
if [ -z $logged_on ]
then
echo "$muser is not logged on."
echo "Exiting script..."
exit
fi
#
# Determine if user allows messaging:
#
allowed=$(who -T | grep -i -m 1 $muser | gawk '{print $2}')
#
if [ $allowed != "+" ]
then
echo "$muser does not allowing messaging."
echo "Exiting script..."
exit
fi
#
# Determine if a message was included:
#
if [ -z "$message" ]
then
echo "No message parameter included."
echo "Exiting script..."
exit
fi
#
# Determine if there is more to the message:
#
whole_message=$message
#
# Send message to user:
#
uterminal=$(who | grep -i -m 1 $muser | gawk '{print $2}')
#
echo $whole_message | write $logged_on $uterminal
#
exit
7.2 向多个终端发送消息
如果用户登录到多个终端,可使用循环遍历所有终端并发送消息。以下是修改后的代码示例:
#!/bin/bash
#
#mu.sh - Send a Message to a particular user
#############################################
#
# Save the username parameter
#
muser=$1
#
# Determine if user is logged on:
#
logged_on=$(who | grep -i -m 1 $muser | gawk '{print $1}')
#
if [ -z $logged_on ]
then
echo "$muser is not logged on."
echo "Exiting script..."
exit
fi
#
# Determine if user allows messaging:
#
allowed=$(who -T | grep -i -m 1 $muser | gawk '{print $2}')
#
if [ $allowed != "+" ]
then
echo "$muser does not allowing messaging."
echo "Exiting script..."
exit
fi
#
# Determine if a message was included:
#
if [ -z $2 ]
then
echo "No message parameter included."
echo "Exiting script..."
exit
fi
#
# Determine if there is more to the message:
#
shift
#
while [ -n "$1" ]
do
whole_message=$whole_message' '$1
shift
done
#
# Get all terminals of the user
#
terminals=$(who | grep -i $muser | gawk '{print $2}')
#
for terminal in $terminals; do
echo $whole_message | write $logged_on $terminal
done
#
exit
7.3 处理仅登录 GUI 的用户
若要判断用户是否仅登录到 GUI,可以通过检查
who
命令的输出是否不包含虚拟控制台终端信息。以下是修改后的代码示例:
#!/bin/bash
#
#mu.sh - Send a Message to a particular user
#############################################
#
# Save the username parameter
#
muser=$1
#
# Determine if user is logged on:
#
logged_on=$(who | grep -i -m 1 $muser | gawk '{print $1}')
#
if [ -z $logged_on ]
then
echo "$muser is not logged on."
echo "Exiting script..."
exit
fi
#
# Check if user is only logged in GUI
#
if ! who | grep -i $muser | grep -q tty; then
echo "$muser is only logged in GUI. Cannot send message."
echo "Exiting script..."
exit
fi
#
# Determine if user allows messaging:
#
allowed=$(who -T | grep -i -m 1 $muser | gawk '{print $2}')
#
if [ $allowed != "+" ]
then
echo "$muser does not allowing messaging."
echo "Exiting script..."
exit
fi
#
# Determine if a message was included:
#
if [ -z $2 ]
then
echo "No message parameter included."
echo "Exiting script..."
exit
fi
#
# Determine if there is more to the message:
#
shift
#
while [ -n "$1" ]
do
whole_message=$whole_message' '$1
shift
done
#
# Send message to user:
#
uterminal=$(who | grep -i -m 1 $muser | gawk '{print $2}')
#
echo $whole_message | write $logged_on $uterminal
#
exit
7.4 发送文件中的长消息
若要发送存储在文件中的长消息,可以使用
cat
命令读取文件内容并通过管道传递给
write
命令。以下是修改后的代码示例:
#!/bin/bash
#
#mu.sh - Send a Message to a particular user
#############################################
#
# Save the username parameter
#
muser=$1
#
# Determine if user is logged on:
#
logged_on=$(who | grep -i -m 1 $muser | gawk '{print $1}')
#
if [ -z $logged_on ]
then
echo "$muser is not logged on."
echo "Exiting script..."
exit
fi
#
# Determine if user allows messaging:
#
allowed=$(who -T | grep -i -m 1 $muser | gawk '{print $2}')
#
if [ $allowed != "+" ]
then
echo "$muser does not allowing messaging."
echo "Exiting script..."
exit
fi
#
# Determine if a file was included:
#
if [ -z $2 ]
then
echo "No file parameter included."
echo "Exiting script..."
exit
fi
#
if [ ! -f $2 ]
then
echo "File $2 does not exist."
echo "Exiting script..."
exit
fi
#
# Send message to user:
#
uterminal=$(who | grep -i -m 1 $muser | gawk '{print $2}')
#
cat $2 | write $logged_on $uterminal
#
exit
7. 总结
通过以上内容,我们学习了如何使用高级功能创建实用的 shell 脚本,包括使用 MySQL 服务器存储数据、使用 lynx 浏览器提取网页数据以及使用 Mailx 程序发送报告。同时,详细介绍了创建一个有趣的消息发送脚本的过程,包括确定系统用户、检查消息接收权限、测试发送消息、创建脚本以及对脚本进行改进。
在创建脚本的过程中,我们使用了多种命令和技巧,如
who
、
mesg
、
write
、
grep
、
gawk
、
shift
和
while
循环等。通过不断改进脚本,我们可以使其更加灵活和强大,满足不同的需求。
希望这些内容能帮助你更好地掌握 shell 脚本的编写,让你在 Linux 系统中更加高效地完成各种任务。
下面是脚本改进功能的总结表格:
| 改进功能 | 实现方法 |
| — | — |
| 使用选项替代参数 | 使用
getopts
命令解析选项 |
| 向多个终端发送消息 | 遍历用户的所有终端,使用
write
命令发送消息 |
| 处理仅登录 GUI 的用户 | 检查
who
命令输出是否包含虚拟控制台终端信息 |
| 发送文件中的长消息 | 使用
cat
命令读取文件内容并通过管道传递给
write
命令 |
以下是脚本改进流程的 mermaid 流程图:
graph TD;
A[开始] --> B[选择改进功能];
B -- 使用选项替代参数 --> C[使用getopts解析选项];
C --> D[修改脚本逻辑];
B -- 向多个终端发送消息 --> E[遍历用户终端];
E --> F[使用write发送消息];
B -- 处理仅登录GUI的用户 --> G[检查终端信息];
G -- 仅登录GUI --> H[输出提示并退出];
G -- 非仅登录GUI --> I[继续执行脚本];
B -- 发送文件中的长消息 --> J[检查文件是否存在];
J -- 文件存在 --> K[使用cat读取文件内容];
K --> L[使用write发送消息];
J -- 文件不存在 --> M[输出提示并退出];
D --> N[结束];
F --> N[结束];
I --> N[结束];
L --> N[结束];
H --> N[结束];
M --> N[结束];
超级会员免费看
78

被折叠的 条评论
为什么被折叠?



