57、编写简单脚本实用程序

编写简单脚本实用程序

在日常的系统管理和数据处理中,编写脚本实用程序可以极大地提高工作效率。本文将详细介绍如何创建每日和每小时的存档脚本,以及如何编写管理账户删除的脚本。

1. 创建每日存档位置

当备份少量文件时,将存档保存在个人目录中是可行的。但如果要备份多个目录,最好创建一个中央存档目录:

$ sudo mkdir /archive
[sudo] password for christine:
$
$ ls -ld /archive
drwxr-xr-x 2 root root 4096 Aug  6 14:20 /archive
$

创建中央存档目录后,需要为特定用户授予访问权限。否则,尝试在该目录中创建文件会失败:

$ mv Files_To_Backup.txt /archive/
mv: cannot move 'Files_To_Backup.txt' to 
'/archive/Files_To_Backup.txt': Permission denied
$

可以通过 sudo 为需要在该目录中创建文件的用户授予权限,或者创建一个用户组。这里创建了一个特殊的用户组 Archivers

$ sudo groupadd Archivers
$
$ sudo chgrp Archivers /archive
$
$ ls -ld /archive
drwxr-xr-x 2 root Archivers 4096 Aug  6 14:20 /archive
$
$ sudo usermod -aG Archivers christine
$
$ sudo chmod 775 /archive
$
$ ls -ld /archive
drwxrwxr-x 2 root Archivers 4096 Aug  6 14:20 /archive
$

用户添加到 Archivers 组后,必须注销并重新登录,组权限才能生效。此时,该组的成员可以在不使用超级用户权限的情况下创建文件:

$ mv Files_To_Backup.txt /archive/
$
$ ls /archive/
Files_To_Backup.txt
$

需要注意的是, Archivers 组的所有成员都可以在该目录中添加和删除文件。为了防止组成员删除彼此的压缩包,可以为目录添加粘滞位。为了保持组织性,可以在 /archive 目录中为每个用户创建子目录。

2. 创建每日备份脚本

Daily_Archive.sh 脚本可以自动将文件存档到指定位置,并使用当前日期唯一标识存档文件。以下是脚本的部分代码:

today=$(date +%y%m%d)
#
# Set Archive File Name
#
backupFile=archive$today.tar.gz
# 
# Set Configuration and Destination File
#
config_file=/archive/Files_To_Backup
destination=/archive/$backupFile
#

destination 变量指定了存档文件的完整路径名, config_file 变量指向包含要存档目录的配置文件。如果需要,可以轻松更改这些变量以指定其他目录和文件。

完整的 Daily_Archive.sh 脚本如下:

#!/bin/bash
#
# Daily_Archive - Archive designated files & directories
########################################################
#
# Gather Current Date
#
today=$(date +%y%m%d)
#
# Set Archive File Name
#
backupFile=archive$today.tar.gz
#
# Set Configuration and Destination File
#
config_file=/archive/Files_To_Backup.txt
destination=/archive/$backupfile
#
######### Main Script #########################
#
# Check Backup Config file exists
#
if [ -f $config_file ] # Make sure the config file still exists.
then           # If it exists, do nothing but continue on.
     echo
else           # If it doesn't exist, issue error & exit script.
     echo
     echo "$config_file does not exist."
     echo "Backup not completed due to missing Configuration File"
     echo
     exit
fi
#
# Build the names of all the files to backup
#
file_no=1              # Start on Line 1 of Config File.
exec 0< $config_file   # Redirect Std Input to name of Config File
#
read file_name         # Read 1st record
#
while [ $? -eq 0 ]     # Create list of files to backup.
do
        # Make sure the file or directory exists.
     if [ -f $file_name -o -d $file_name ]
     then
          # If file exists, add its name to the list.
          file_list="$file_list $file_name"
     else
          # If file doesn't exist, issue warning
          echo
          echo "$file_name, does not exist."
          echo "Obviously, I will not include it in this archive."
          echo "It is listed on line $file_no of the config file."
          echo "Continuing to build archive list..."
          echo
     fi
#
     file_no=$[$file_no + 1]  # Increase Line/File number by one.
     read file_name           # Read next record.
done
#
#######################################
#
# Backup the files and Compress Archive
#
echo "Starting archive..."
echo
#
tar -czf $destination $file_list 2> /dev/null
#
echo "Archive completed"
echo "Resulting archive file is: $destination"
echo
#
exit

这个脚本有一些可以改进的地方。例如,如果没有要备份的现有文件或目录, $file_list 为空怎么办?可以使用 if-then 语句来检查这个问题。还可以使用 tar 命令的 -v 选项并重定向标准输出以创建报告或日志。

3. 运行每日存档脚本

在测试脚本之前,需要更改脚本文件的权限,为文件所有者授予执行权限:

$ ls -og Daily_Archive.sh
-rw-r--r-- 1 2039 Aug  6 14:13 Daily_Archive.sh
$
$ chmod u+x Daily_Archive.sh
$
$ ls -og Daily_Archive.sh
-rwxr--r-- 1 2039 Aug  6 14:13 Daily_Archive.sh
$

测试 Daily_Archive.sh 脚本很简单:

$ ./Daily_Archive.sh

/home/christine/Does_not_exist/, does not exist.
Obviously, I will not include it in this archive.
It is listed on line 3 of the config file.
Continuing to build archive list...

Starting archive...

Archive completed
Resulting archive file is: /archive/archive200806.tar.gz

$

可以看到,脚本检测到一个不存在的目录 /home/christine/Does_not_exist ,并告知该目录在配置文件中的行号,然后继续构建存档列表并进行存档。

由于这是一个重要的脚本,可以使用 anacron 使其每天自动运行,而无需手动启动。

4. 创建每小时存档脚本

在高流量的生产环境中,文件变化迅速,每日存档可能无法满足需求。如果要将存档频率提高到每小时,需要考虑一些问题。当每小时备份文件并使用 date 命令为每个压缩包添加时间戳时,文件名会变得很混乱。可以为存档文件创建一个目录层次结构,如下所示:

graph TD;
    /archive/hourly --> 01;
    /archive/hourly --> 02;
    01 --> 01;
    01 --> 02;
    02 --> 01;
    02 --> 02;

首先,需要创建新目录 /archive/hourly 并设置适当的权限:

$ sudo mkdir /archive/hourly
[sudo] password for christine:
$
$ sudo chgrp Archivers /archive/hourly
$
$ ls -ogd /archive/hourly/
drwxr-xr-x 2 4096 Aug  7 15:56 /archive/hourly/
$
$ sudo chmod 775 /archive/hourly
$
$ ls -ogd /archive/hourly/
drwxrwxr-x 2 4096 Aug  7 15:56 /archive/hourly/
$

新目录设置好后,可以将每小时存档的配置文件 Files_To_Backup.txt 移动到新目录中:

$ cat Files_To_Backup.txt
/usr/local/Production/Machine_Errors/
/home/Development/Simulation_Logs/
$
$ mv Files_To_Backup.txt /archive/hourly/
$

接下来创建 Hourly_Archive.sh 脚本,以下是脚本的上半部分:

#!/bin/bash
#
# Hourly_Archive - Every hour create an archive
################################################
#
# Set Configuration File
#
config_file=/archive/hourly/Files_To_Backup.txt
#
# Set Base Archive Destination Location
#
basedest=/archive/hourly
#
# Gather Current Day, Month & Time
#
day=$(DATE +%D)
month=$(DATE +%M)
time=$(DATE +%K%M)
#
# Create Archive Destination Directory
#
mkdir -p $basedest/$month/$day
#
# Build Archive Destination File Name
#
destination=$basedest/$month/$day/archive$time.tar.gz
#
######### Main Script #########################
[…]

Hourly_Archive.sh 脚本获取日期和时间信息,创建存档目录,并使用 tar 命令创建并压缩存档文件。

5. 运行每小时存档脚本

在将 Hourly_Archive.sh 脚本添加到 cron 表之前,最好先进行测试。首先需要修改脚本的权限,并获取当前的小时和分钟,以便验证最终存档文件的文件名是否正确:

$ chmod u+x Hourly_Archive.sh
$
$ date +%k%M
1610
$
$ ./Hourly_Archive.sh

Starting archive...

Archive completed
Resulting archive file is: 
/archive/hourly/08/07/archive1610.tar.gz

$
$ ls /archive/hourly/08/07/
/archive/hourly/08/07/archive1610.tar.gz
$

脚本第一次运行正常,创建了相应的月和日目录,并创建了正确命名的存档文件。

如果在小时为个位数时运行脚本,存档文件名可能只有三位数字。如果希望存档文件名始终为四位数字,可以将脚本中的 TIME=$(date +%k%M) 修改为 TIME=$(date +%k0%M)

再次运行脚本进行测试:

$ date +%k%M
1615
$
$ ./Hourly_Archive.sh

Starting archive...

Archive completed
Resulting archive file is: 
/archive/hourly/08/07/archive1615.tar.gz

$
$ ls /archive/hourly/08/07/
archive1610.tar.gz  archive1615.tar.gz
$

脚本再次正常运行,没有出现问题,现在可以将其添加到 cron 表中。

6. 管理账户删除

管理本地用户账户不仅仅是添加、修改和删除账户,还需要考虑安全问题、保留工作的需求以及准确删除账户。这可能是一项耗时的任务,编写脚本实用程序可以节省大量时间。

6.1 获取所需功能

删除本地账户是账户管理中较复杂的任务,至少需要执行以下四个操作:
1. 获取要删除的正确用户账户名。
2. 终止系统上当前属于该账户的所有进程。
3. 确定系统上属于该账户的所有文件。
4. 删除用户账户。
很容易遗漏某个步骤,本节的脚本可以帮助避免此类错误。

6.2 获取正确的账户名

账户删除过程的第一步是获取要删除的正确用户账户名。由于这是一个交互式脚本,使用 read 命令获取账户名,并添加 -t 选项设置超时时间为60秒:

echo "Please enter the username of the user " 
echo -e "account you wish to delete from system: \c"
read -t 60 answer

为了给用户三次回答问题的机会,使用 while 循环和 -z 选项检查 answer 变量是否为空:

while [ -z "$answer" ]
do
    echo "Please enter the username of the user " 
    echo -e "account you wish to delete from system: \c"
    read -t 60 answer
done

当第一次提问超时时,需要与脚本用户进行沟通。使用 case 语句根据 ask_count 变量的值显示不同的消息:

case $ask_count in
2)
     echo
     echo "Please answer the question."
     echo
;;
3)
     echo
     echo "One last try...please answer the question."
     echo
;;
4)
     echo
     echo "Since you refuse to answer the question..."
     echo "exiting program."
     echo
     #
     exit 
;;
esac

为了使脚本代码更简洁,将这部分代码封装成一个函数 get_answer

function get_answer {
    #
    unset answer
    $ask_count=0
    #
    while [ -z "$answer" ]
    do
        ask_count=$[ $ask_count + 1 ]
        #
        case $ask_count in
        2)
            echo
            #...
        esac
        #
        echo
        if [ -n "$line2" ]
        then                 #Print 2 lines
            echo $line1
            echo -e $line2" \c"
        else                    #Print 1 line
            echo -e $line1" \c"
        fi
        #
        read -t 60 answer
    done
    # 
    unset line1
    unset line2
    #
}  #End of get_answer function

调用 get_answer 函数获取要删除的账户名:

line1="Please enter the username of the user " 
line2="account you wish to delete from system:"
get_answer
user_account=$answer
6.3 验证输入的账户名

由于可能存在输入错误,需要验证输入的用户账户名。使用 get_answer 函数询问用户是否确认要删除该账户:

line1="Is $user_account the user account " 
line2="you wish to delete from the system? [y/n]"
get_answer

使用 case 语句处理用户的回答:

case $answer in
y|Y|YES|yes|Yes|yEs|yeS|YEs|yES ) 
#
;;
*)                   
    echo 
    echo "Because the account, $user_account, is not "
    echo "the one you wish to delete, we are leaving the script..."
    echo 
    exit
;;
esac

为了简化 case 语句,使用 cut 命令将 answer 变量的内容截取为第一个字符:

answer=$(echo $answer | cut -c1)

简化后的 case 语句如下:

case $answer in
y|Y) 
#
;;
[…]
esac

由于脚本在不同位置需要处理多个是/否回答,因此创建一个函数 process_answer 来处理这个任务:

function process_answer {
    #
    answer=$(echo $answer | cut -c1)
    #
    case $answer in
    y|Y) 
    ;;
    *)                   
        #...
    esac
}

通过以上步骤,我们可以创建实用的脚本程序来完成每日和每小时的文件存档,以及安全准确地管理用户账户的删除。这些脚本可以提高工作效率,减少人为错误。

编写简单脚本实用程序

7. 优化账户删除脚本

在账户删除脚本中,虽然已经实现了获取正确账户名和验证账户名的功能,但还有一些可以优化的地方。

7.1 错误处理的细化

在获取账户名和验证账户名的过程中,除了超时和输入错误的情况,还可能存在其他异常。例如,输入的账户名可能在系统中并不存在。可以在验证账户名时,增加对账户是否存在的检查。

if ! id "$user_account" &>/dev/null; then
    echo 
    echo "The account, $user_account, does not exist in the system."
    echo "We are leaving the script..."
    echo 
    exit
fi

这段代码使用 id 命令检查账户是否存在,如果不存在则输出错误信息并退出脚本。

7.2 日志记录

为了方便后续的审计和问题排查,可以在脚本中添加日志记录功能。在关键步骤,如获取账户名、验证账户名、终止进程、删除账户等,将操作信息记录到日志文件中。

log_file="/var/log/account_deletion.log"
echo "$(date): Starting account deletion process for $user_account" >> $log_file

在脚本结束时,也可以记录操作结果:

echo "$(date): Account $user_account has been successfully deleted." >> $log_file
8. 脚本的扩展与应用

除了上述的每日存档、每小时存档和账户删除脚本,还可以根据实际需求对脚本进行扩展和应用。

8.1 多服务器备份

如果需要对多个服务器上的文件进行备份,可以将每日存档脚本进行扩展。通过 SSH 连接到其他服务器,获取需要备份的文件,并将其复制到本地进行存档。

# 定义服务器列表
servers=("server1.example.com" "server2.example.com")
for server in "${servers[@]}"; do
    scp user@$server:/path/to/files/* /archive/temp/
    # 将临时目录中的文件添加到存档列表
    file_list="$file_list /archive/temp/*"
done
8.2 自动化部署

在开发和运维过程中,脚本可以用于自动化部署。例如,当有新的代码更新时,自动将代码部署到服务器上,并重启相关服务。

# 拉取最新代码
git pull origin master
# 安装依赖
npm install
# 重启服务
systemctl restart myapp.service
9. 脚本的维护与监控

编写好脚本后,还需要进行维护和监控,以确保脚本的正常运行。

9.1 定期检查

定期检查脚本的运行情况,查看日志文件,确保没有出现错误。可以使用 cron 任务定期执行检查脚本。

# 每天凌晨 2 点检查存档脚本的日志
0 2 * * * grep -i error /var/log/archive.log
9.2 监控脚本状态

可以使用监控工具,如 Nagios 或 Zabbix,监控脚本的运行状态。当脚本出现异常时,及时发送警报。

graph LR;
    A[脚本运行] --> B{是否成功};
    B -- 是 --> C[正常];
    B -- 否 --> D[发送警报];
10. 总结

通过编写脚本实用程序,我们可以实现文件的自动存档、账户的安全删除等功能,提高工作效率,减少人为错误。在编写脚本时,需要考虑各种异常情况,进行错误处理和日志记录。同时,还可以根据实际需求对脚本进行扩展和应用,实现更多的自动化任务。最后,要对脚本进行维护和监控,确保脚本的正常运行。

以下是一个总结表格,展示了不同脚本的功能和关键步骤:
| 脚本名称 | 功能 | 关键步骤 |
| — | — | — |
| Daily_Archive.sh | 每日文件存档 | 创建存档目录、设置权限、获取日期、构建存档文件名、检查配置文件、构建文件列表、执行存档操作 |
| Hourly_Archive.sh | 每小时文件存档 | 创建目录层次结构、设置权限、移动配置文件、获取日期和时间、创建存档目录、构建存档文件名、执行存档操作 |
| Delete_User.sh | 账户删除 | 获取正确账户名、验证账户名、终止进程、删除账户、记录日志 |

通过这些脚本和相关的优化、扩展、维护措施,我们可以构建一个高效、稳定的自动化系统,满足日常工作的各种需求。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值