仙石浩明の日記

2006年5月5日

su & emacsclient hatena_b

普段 emacs を使っている人に質問なのですが、
root 作業するときどうしてますか?

私は、GNU Screen の中で emacs をずーっと立ち上げっぱなしにしていて、 ほとんどの作業を emacs の中で行なっています。 もちろんコマンドラインから何かを実行するときも、 emacs の shell モード (正確に言うと j-shell.el なんですが ^^;) の中で 行なっています。

いきおい、root になるときも shell モードで「su」を実行することになります。 で、root 権限でファイルを読み書きしようとしたとき、 どうするのがいいか、というのが問題です。

そんなの root で emacs を実行しておけばええやん、 という声が聞こえてきそうですが、 root 権限で常に emacs が動いている、というのは 想像するのもおぞましいですし、かといって 編集するたびに root で emacs を立ち上げるのは、 (起動に時間がかかるので) もっと嫌です。 そもそも root 権限で emacs (に限らずエディタならなんでも) を 立ち上げるには、 Screen の別ウィンドウで行なわなければならず、 ウィンドウの切替で作業がかなり煩雑になってしまいます。

ちなみに、ずーっと以前は、ange-ftp を使っていました。 つまり、emacs から root@localhost へ ftp して (root の) ファイルを読んできて編集し、 保存するときも ftp で書込む。 この方法は root でログインする、 という気持ち悪さがもともとあったので、 ftpd を走らせなくなったのを機会に止めました。

で、それ以来使っているのが、 今回紹介する emacsclient を使う方法です。 もしもっといい方法があるぞっ、というかたがいらっしゃいましたら、 是非教えてください (_O_)。

- o -

emacs 上で「M-x server-start」と入力すると、 emacsserver (gnuserv) を 走らせておくことができます。 この状態で、コマンドラインから

% emacsclient ファイル名

などと emacsclient (gnuclient) を実行すると、 引数に指定したファイルを、emacs で編集することができます。

したがって、root 権限でファイルを編集するときは、 まずファイルを emacs で読み書きできるようテンポラリファイルへコピーし、 それを emacsclient で開き、 テンポラリファイルが変更されたら、 それを元のファイルへ root 権限で書き出せばよいことになります。

私は suemacs と名付けた以下のような perl スクリプトを書いて使っています。 例えば

# suemacs /root/.cshrc

などと実行すると、 /root/.cshrc の内容が /tmp/suemacs5544/.cshrc_0 へコピーされ、 emacsclient /tmp/suemacs5544/.cshrc_0が実行されます。

suemacs スクリプト

#!/usr/bin/perl
$user = $ENV{'LOGNAME'};
$tmp = "/tmp/suemacs$$";
$Debug = 0;
$Once = 0;
use POSIX ":sys_wait_h";
use Getopt::Std;
getopts('do') || &help;
$Debug = 1 if $opt_d;
$Once = 1 if $opt_o;

sub help {
    print <<EOF;
Usage: suemacs <opt> <file>...
opt:  -o        ; write once on closing
      -d        ; for debug
EOF
    exit 1;
}

if ($> != 0 || ! $user) {
    exec "emacsclient", @ARGV;
}
($login, $pass, $uid, $gid) = getpwnam($user) or die;
print "login: $login,  uid: $uid,  gid: $gid\n" if $Debug;
umask 077;
mkdir $tmp || die;
chown $uid, $gid, $tmp;

for ($i=0; $i < @ARGV; $i++) {
    my $tmpfile = $ARGV[$i];
    $tmpfile =~ s@.*/@@;
    $tmpfile = "$tmp/${tmpfile}_$i";
    push @argv, $tmpfile;
    my $mtime = &cp($ARGV[$i], 0, $tmpfile);
    push @mtime, $mtime;
    chown $uid, $gid, $tmpfile;
}
if (!$Debug) {
    if (!fork) {
        close(STDOUT);
        close(STDERR);
        open(">&STDOUT", "/dev/null") || die;
        open(">&STDERR", "/dev/null") || die;
    } else {
        exit 0;
    }
}
if (!fork) {
    ($(, $)) = ($gid, $gid);
    ($<, $>) = ($uid, $uid);
    exec "emacsclient", @argv;
    exit 0;
}
my ($ret);
do {
    sleep 1;
    $ret = waitpid(-1,WNOHANG);
    print "ret: $ret, status: $?\n" if $ret > 0 && $Debug;
    for ($i=0; $i < @argv; $i++) {
        $mtime[$i] = &cp($argv[$i], $mtime[$i], $ARGV[$i])
            if $ret > 0 || ! $Once;
        unlink $argv[$i] if $ret > 0;
    }
} until ($ret > 0);
rmdir $tmp;
exit 0;

sub cp {
    my ($src, $stime, $dst) = @_;
    my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
        $atime,$mtime,$ctime,$blksize,$blocks) = stat($src);
    if ($stime == $mtime) {
        print "$src is not modified.\n" if $Debug;
        return $mtime;
    }
    print "cp $src $dst\n" if $Debug;
    open(SRC, $src) || die;
    open(DST, ">$dst") || die;
    while (<SRC>) {
        print DST;
    }
    close(DST);
    close(SRC);
    utime $atime, $mtime, $dst;
    return $mtime;
}
Filed under: プログラミングと開発環境 — hiroaki_sengoku @ 19:35

4 Comments »

  1. sudoedit+emacsclientとか。sudoeditとsuemacsはあんまかわりませんけど。

    Comment by (ひ) — 2006年5月7日 @ 00:52

  2. あとは、trampを使って/su::/root/.cshrcを開くというのはどうすかね?

    Comment by (ひ) — 2006年5月7日 @ 01:07

  3. sudoedit というのがあるんですね。φ(..)メモメモ
    確かに suemacs と同じような発想のものですね。
    どちらの方法も、編集対象がテンポラリファイルのパス名になるのが不便…
    ssh で root にログインするのが気持ち悪いのですよねぇ > tramp
    たしかに ftp に比べれば 100万倍マシなんですが、shell mode で su しているのに、それとは別の方法で root になる、というのがなんとも…

    Comment by 仙石浩明 — 2006年5月7日 @ 10:58

  4. Emacs で設定ファイルを編集する

    [http://d.hatena.ne.jp/higepon/20060504/1146756872:title=ひげぽん OSとか作っちゃうかMona- – httpd.confの編集を vi でやっているとストレスがたまる、Emacs好きな人は jed を使いましょう] [http://d.hatena.ne.jp/odz/20060505/1146792377:title=odzの日記 – ng] [ht…

    Comment by odzの日記 — 2006年5月8日 @ 11:00

RSS feed for comments on this post.

Leave a comment