sudoers で許可したディレクトリだけ削除させる sudorm

たとえばリモートから ssh でログの退避を行っている場合、コピーが完了したログをどうやって削除するかが問題になったりする。というのは、ログファイルの owner はたいてい root だから、ssh 経由だと削除できない。古典的な方法としては setuid された (あるいは suidperl とか使った) 専用プログラムを書くんだろうけど、退避するディレクトリが多くなってくると、その数だけ専用プログラムを書くのもばからしくなってくるわけで。

つーわけで sudo で削除できる sudorm 書いてみた。

#! /usr/bin/perl

use strict;
use warnings;

my ($dir, $test);

# obtain base dir (and append / if missing)
$dir = shift @ARGV || '';
unless ($dir =~ m|^/|) {
    print "Usage: $0 base-dir [-t] pattern...\n";
    exit 99;
}
$dir .= '/' unless $dir =~ m|/$|;

# test mode check
if (@ARGV && $ARGV[0] eq '-t') {
    $test = 1;
    shift @ARGV;
}

# remove files
foreach my $f (glob join ' ', map { $dir . $_ } @ARGV) {
    if ($f =~ /^$dir/) {
        if ($test) {
            print "remove $f\n";
        } else {
            unlink $f
                or warn "failed to remove $f: $!\n";
        }
    } elsif ($f ne '') {
        warn "file out of range: $f\n";
    }
}

あとは /etc/sudoers に、

maintenance ALL=NOPASSWD:/usr/local/bin/sudorm /var/log/httpd/example.com *
maintenance ALL=NOPASSWD:/usr/local/bin/sudorm /var/log/httpd/example.jp *

とか書いておいて、リモートから

ssh maintenance@example.com sudo sudorm /var/log/httpd/example.com "access_log.*.gz"
ssh maintenance@example.com sudo sudorm /var/log/httpd/example.jp "access_log.*.gz"

みたく呼び出せばいい。認証はもちろん公開鍵で。