用Perl脚本搞定日常运维自动化

在不少老派运维工程师的工具箱里,ref="/tag/2034/" style="color:#B2A89E;font-weight:bold;">Perl 脚本依然占有一席之地。虽然现在 Python 更流行,但在一些老旧系统或特定场景下,Perl 依然是处理文本、日志分析和批量任务自动的得力工具。

为什么还在用 Perl?

很多公司的内部系统是十年前甚至更早搭建的,那时候 Perl 正是系统管理的主流语言。至今仍有大量运行中的监控脚本、日志轮转工具和配置生成器是用 Perl 写的。维护这些系统时,改一行 Perl 脚本比重写整个流程更现实。

比如,某个 CDN 节点每天凌晨要清理临时缓存目录,同时记录清理前后的磁盘使用情况。这种重复性高、逻辑简单的任务,用几行 Perl 就能搞定:

#!/usr/bin/perl
use strict;
use warnings;

my $log_file = "/var/log/cleanup.log";
my $dir = "/tmp/cache";

open(my $fh, '>>', $log_file) or die "无法打开日志文件: $!\n";

print $fh "【开始】清理目录 $dir - " . localtime() . "\n";

my $before = `df -h /tmp`;
print $fh "清理前磁盘状态:\n$before\n";

system("rm -rf $dir/*");

my $after = `df -h /tmp`;
print $fh "清理后磁盘状态:\n$after\n";
print $fh "【完成】清理结束\n---\n";

close($fh);

处理日志就像切菜一样顺手

Perl 的正则表达式能力非常强大,处理 Nginx 或 Apache 日志时特别顺手。比如你想从访问日志中抓出所有 404 错误,并统计访问最多的无效路径:

#!/usr/bin/perl
use strict;

my %not_found;

open(my $fh, '<', '/var/log/nginx/access.log') or die $!;

while (<$fh>) {
    if (/"\S+\s+\S+\s+HTTP\/\d\.\d"\s+404\s+/) {
        if (/"\S+\s+(\S+)\s+HTTP/) {
            $not_found{$1}++;
        }
    }
}
close $fh;

print "Top 10 404 请求路径:\n";
for my $path (sort { $not_found{$b} <=> $not_found{$a} } keys %not_found) {
    print "$not_found{$path} 次: $path\n";
    last if --$ARGV[0] == 0; # 支持传参,例如 perl script.pl 10
}

这个脚本跑一遍,就能快速定位是不是有爬虫在扫不存在的接口,或者前端静态资源路径写错了。

自动化不只是跑命令

真正的运维自动化,是要让机器自己发现问题、尝试修复、再上报结果。比如一个检查 MySQL 是否响应的脚本,可以在失败时尝试重启服务,并发邮件通知管理员:

#!/usr/bin/perl
use Mail::Sendmail;

my $ping_result = `mysqladmin -u root ping 2>/dev/null`;

if ($ping_result !~ /mysqld is alive/) {
    system("systemctl restart mysqld");
    sleep(3);
    
    my $retry = `mysqladmin -u root ping 2>/dev/null`;
    if ($retry =~ /mysqld is alive/) {
        sendmail(
            To      => 'admin@company.com',
            From    => 'monitor@server.local',
            Subject => 'MySQL 已自动恢复',
            Message => '数据库曾无响应,已尝试重启并恢复正常。'
        );
    } else {
        sendmail(
            To      => 'admin@company.com',
            Subject => 'MySQL 重启失败,请立即处理',
            Message => '数据库无法响应,自动重启未成功。'
        );
    }
}

把这类脚本加入 crontab,每五分钟跑一次,相当于给系统装了个“自动急救包”。

尽管 Perl 的语法看起来有点怪,像用符号堆出来的咒语,但它的实用性和执行效率在特定场景下依然能打。特别是在没有外部依赖、只靠系统自带模块就能跑起来这一点上,对运维来说就是硬通货。