2005-06-26 (Sun)

* cron 登録ジョブ crontab のバックアップ

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [unix] [バックアップ]

ユーザレベルでの crontab のバックアップってどうするのがいいんだろう? /var/cron/tabs/USER_NAME をバックアップすればいいのかな? 一応コマンドでやるか。

~/etc に一日一回 crontab の中身をダンプする。
# crontab backup
8 0 * * * crontab -l >$HOME/etc/crontab_backup_`date +\%a`

date コマンドの引数の % の前に \ をつけているのは、crontab の場合 % を \% にエスケープする必要があるため。

Manpage of CRONTAB
http://www.linux.or.jp/JM/html/cron/man5/crontab.5.html
「第 6」フィールド (行の残りの部分) には実行されるコマンドを指定する。その行のコマンド部 (改行文字または % 文字まで) が /bin/sh (またはその crontab ファイルの SHELL 環境変数で指定されたシェル) によって実行される。コマンド中にパーセント記号 (%) がバックスラッシュ (\) によってエスケープされずに置かれていると、改行文字に置き換えられ、最初に現れた % 以降の全てのデータは標準入力としてコマンドに送られる。

ホームディレクトリは ~/tmp を除き丸ごとバックアップ。暗号化して他のマシンに転送。

2005-04-17 (Sun)

* Bloglines の登録データをバックアップする シェルスクリプト

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [バックアップ] [シェルスクリプト] [RSS]

bloglines に登録したサイト一覧を定期的に自動で OPML にエクスポートしてバックアップする方法。

- Bloglines の登録データをバックアップするシェルスクリプトの概要

http://www.bloglines.com/export に Bloglines の Cookie 付きで HTTP GET し、返ってきたレスポンスを保存する。あとはこれを cron などで定期的に自動実行すれば OK。

やっぱり自分のデータは手元に置いておきたい。他の RSS リーダに乗り換えるときに手元に OPML があれば楽だろうから、定期的なバックアップは取っておきたいし。

- Bloglines の登録データは OPML でエクスポートできる

Bloglines のアカウントを持っている人なら、http://www.bloglines.com/export にアクセスすると Bloglines で購読しているサイトの一覧を OPML でエクスポートすることができる。http://www.bloglines.com/export には特にユーザを識別するようなクエリが付いていない。おそらく Cookie にユーザーデータが入っていて、それでユーザを識別しているんだろう。Web アプリケーションの定石だね。

2005-04-18 追記。「Bloglines から エクスポートした OPML が文字化けする現象への対処」という記事を書いた。

- Live Http headers で HTTP トランザクションの中身を調べる

どんな Cookie が Bloglines に送信されているかを見てみる。

Firefox を起動し、2005-04-16 の「Live Http headers - HTTP ヘッダ表示ツール」で書いた Live Http headers で HTTP ヘッダを表示させながら Bloglines にアクセスする。Bloglines の登録に使ったメールアドレスとか、色々それらしき情報を見ることができた。私のアカウントを保護するため、一部伏せ字や文字の削除をした。

http://www.bloglines.com/export

GET /export HTTP/1.1
Host: www.bloglines.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; ja-JP; rv:1.7.6) Gecko/20050318 Firefox/1.0.2
Accept: text/xml,application/xml,application/xhtml+xml, text/html;q=0.9, text/plain;q=0.8, image/png,*/*;q=0.5
Accept-Language: ja,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Cookie: BloglinesLang=0; BloglinesTracker=MXk4zPhcOWV3tjEJV14gNY; BloglinesEmail=blog****@**********.com; clickedFoldersubtree=; clickedFoldermanagetree=

HTTP/1.x 200 OK
Date: Sun, 17 Apr 2005 12:47:22 GMT
Server: Apache/1.3.31 (Unix)
Cache-Control: no-cache, must-revalidate, no-cache="Set-Cookie", private
Expires: Fri, 01 Jan 1990 00:00:00 GMT
Pragma: no-cache
Set-Cookie: BloglinesLang=0; path=/; expires=Monday, 17-Apr-2006 23:59:59 GMT
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/xml; charset=utf-8

ちなみに Cookie を無効にして http://www.bloglines.com/export にアクセスすると、ログイン画面に飛ばされた。つまり、http://www.bloglines.com/export に Cookie 付きでアクセスすればいいということ。

Cookie の有効期限は expires=Monday, 17-Apr-2006 23:59:59 GMT なので、一年間だ。

- Bloglines の登録データをバックアップするシェルスクリプト

Perl などで書いても良いけど、これくらいだったらシェルスクリプトで十分。wget で HTTP リクエストを投げ、date コマンドで7世代分残す。

wget で送信する Cookie は --header='' に記述する。さっきの Live Http headers で表示させた Cookie をそのまま使えばいい。

#!/bin/sh

wget --header='Cookie: BloglinesLang=0; BloglinesTracker=MXk4zPhcOWV3tjEJV14gNY; BloglinesEmail=blog****@**********.com; clickedFoldersubtree=; clickedFoldermanagetree=' http://www.bloglines.com/export -O $HOME/etc/bloglines`date +%u`.opml

ちなみに、date コマンドの引数の +%u は 月曜日を1とし、日曜日を7とする数字で、毎日出力が変わる。7世代分残したいからこれを使った。
date --help の結果から抜粋。
%u  day of week (1..7);  1 represents Monday"

上記スクリプトを export_bloglines_opml.sh というファイル名で保存する。
crontab に登録し、毎日 01:01 に実行する。
1 1 * * * nice -19 /home/aqua/script/export_bloglines_opml.sh

ホームディレクトリは 2004-11-09 の「GMail をバックアップストレージとして使う」で書いたスクリプトで毎日バックアップしている。これでとりあえず大丈夫でしょう。Cookie の有効期限までは自動でバックアップがとれる。

- public 設定の人は Cookie 不要

2005-04-19 追記。Public 設定にしておけば Cookie 不要で OPML をエクスポートできる。

void GraphicWizardsLair( void ); // http://www.otsune.com/diary/ の otsune さんから以下のメールを頂いた。ありがとうございます。

public設定になっているIDの人は
http://www.bloglines.com/export?id=hoge
というURLでもエクスポートできるようです。

なるほど。public ってどこで設定するんだろう? ちょっと調べてみよう。

わかった。Bloglines にログインして、右上の「アカウント」の「ブログ設定」から Public 属性を設定できる。パンくずリストで言うと、「ホーム > アカウント > ブログ設定」。ここでユーザ名を登録して、「ブログの公開設定」を「はい」にすれば良い。

ブログの公開設定:
○ はい、ブログとブログロールを公開します
● いいえ、ブログを公開しません

あなたのアカウントを非公開にすると、あなだだけ見ることができます。
公開すると、あなたのブログにアクセスできます http://www.bloglines.com/blog/************

やり方も分かったし、Public 設定を試してみたい。テスト用のアカウントを登録して Public にしてみよう。アカウント名は最近鉄拳5のおまけにも付いた StarBlade がいいかな。

http://www.bloglines.com/export?id=StarBlade
<?xml version="1.0" encoding="utf-8"?>
<opml version="1.0">
<head>
    <title>Bloglines Subscriptions</title>
    <dateCreated>Mon, 18 Apr 2005 15:03:26 GMT</dateCreated>
    <ownerName>StarBlade</ownerName>
</head>
<body>
  <outline title="Subscriptions">
    <outline title="Bloglines | News" htmlUrl="http://www.bloglines.com" type="rss" xmlUrl="http://www.bloglines.com/rss/about/news" />
    <outline title="Landscape - エンジニアのメモ" htmlUrl="http://sonic64.com/" type="rss" xmlUrl="http://sonic64.com/cl.xml" />
    <outline title="Landscape - エンジニアのメモ" htmlUrl="http://sonic64.com/" type="rss" xmlUrl="http://sonic64.com/cl-full.xml" />
    <outline title="@IT" htmlUrl="http://www.atmarkit.co.jp" type="rss" xmlUrl="http://www.atmarkit.co.jp/rss/rss.xml" />

</outline>
</body>
</opml>

なるほど、そのまま OPML でエクスポートできた。確かにこれならいちいち Cookie をセットしなくていいので簡単かつ確実に OPML をエクスポートできる。公開してる人にはこっちの方が楽で良いね。秘密主義の私にはできないけど。、

ちなみに、RSS 登録時に「非公開」扱いにしたサイトは表示されない。
フィードを登録していることを:
  公開
  非公開

非公開の登録はブログロールには表示されません

もうひとつ分かったこと。「ホーム > アカウント > ブログ設定」でユーザ名だけ登録しておいて「いいえ、ブログを公開しません」を選んで http://www.bloglines.com/export?id=************ にアクセスすると Internal Server Error になる。Bloglines 開発チームの考慮漏れかな?

いろいろ調べて好奇心を満たした後、ふと Bloglines を見ると「共有」という怪しげなタブがあった。見てみると、試したことがちゃんと書いてあった。最初に見ておけば良かったね。

Bloglines | あなたの登録をシェア
http://www.bloglines.com/help/share
ホーム > ヘルプ > ブログロールウィザード

Bloglinesではあなたが登録しているフィードを2通りの方法でほかの人と共有することができます。1つ目の方法はあなたのプロファイルで共有を許可する方法です。共有設定をオンにすると、あなたが登録しているフィードがすべて公開されます。登録フィードの一覧を表示した状態で編集リンクをクリックすれば個別のフォルダや登録フィードを非公開にすることができます。非公開フォルダや非公開登録フィードはブログロールや/blogビューには表示されません。

/public

ブログロールに加えて、公開登録フィードはBloglinesのウェブサイトで公開されます。あなたの公開フィードは次のURLから参照できます:

http://www.bloglines.com/public/StarBlade
あなたの公開フィードはOPMLファイルとしてエクスポートされます。

Public 設定にしていれば http://www.bloglines.com/export?id=StarBlade だけじゃなく、 http://www.bloglines.com/public/StarBlade という URL でも OPML をエクスポートできるんだね。

- http://www.bloglines.com/public/StarBlade が OPML エクスポートじゃなくなった?

2005-04-19 追記。
なんかいろいろいじってたら http://www.bloglines.com/public/StarBlade が OPML エクスポートじゃなくて単なるフィード紹介ページみたいになっちゃった。OPML をバックアップするという使い方なら、http://www.bloglines.com/export?id=StarBlade の記法が一番確実な模様。

- w3m を使って Bloglines の OPML をエクスポート

public 設定にできない人向けの楽なエクスポート方法を、読書記録ChangeLog http://dkiroku.com/ のうぞよとさんが書いてくださった。

Bloglines の登録データをバックアップする シェルスクリプト
http://dkiroku.com/2005-04-19-2.html
w3mを使用すればもっと簡単です。
(1)w3mでhttp://www.bloglines.com/exportなどにアクセス。
(2)手作業でログインする。
(3)いったんw3mを終了
(4)以下のコマンドを実行
w3m \
-config /home/usename/.w3m/config \
-cookie \
http://www.bloglines.com/export > export.xml

w3mを使用すれば簡単にクッキーを食わせることが可能なのです。
Yahooファイナンスのポートフォリオ機能などでも使用できます。

おお、なるほど。HTTP リクエストヘッダを表示させるといった、面倒なことが必要ないというところが素晴らしい。w3m はテキストベースのウェブブラウザだし、コマンドラインとの相性も良いはず。さっそくやってみよう・・・と思ったけど、手元の FreeBSD マシンには w3m 入ってないや。あとで試すことにする。

2004-11-20 (Sat)

* ssh + tar で安全なファイルコピー

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [シェルスクリプト] [ssh] [バックアップ]

2004-11-18 の「scp + tar + gpg で暗号化ネットワークバックアップ」について指摘を頂いた。

Misc Change Log 安全なファイルコピー
http://quasiquote.org/log/Memo/ssh_filecopy.html
http://sonic64.hp.infoseek.co.jp/2004-11-18.html#2004-11-18-1

ssh + tar じゃいかんのかいな。 rsh の時代からの基本だと思うのだが。

(cd path && tar cf - .) | ssh user@hostname "(cd path && tar xvfp -)"
暗号化したければ、送信側は tar の後、受信側は tar の前にいれてやればよい。何のために ssh 使ってるかわからないけど。

メンドイが、scp や sftp でもできなくはない。ヒントは mkfifo。でも本末転倒。だって scp も sftp も ssh のラッパーだから(少なくとも OpenSSH は。他の処理系はどうなのかな?)。

なんか変なこと書いてる?

ありがとうございます。恥ずかしながら、「rsh の時代からの基本」を知りませんでした。そもそも rcp や rsh は使ったことなかったりします。ssh + tar なら、出力を直接標準入力に渡したいという要件は満たしています。

2004-11-18 の「scp + tar + gpg で暗号化ネットワークバックアップ」を書いた後、FreeBSD QandA 2255 http://www.jp.freebsd.org/QandA/HTML/2255.html を読んでいて、ssh の標準入出力を使う方法があることを知って試してみてはいました。ただ、使い勝手とセキュリティの兼ね合いがまだできてなかったので公開してませんでした。

ローカルマシンで以下を実行し、tar + gpg したデータを ssh に渡してアップロードする。
echo $PASS_PHRASE | { tar --bzip2 -cf - $TAR_TARGET |gpg --batch -c --cipher-algo AES256 --force-mdc --passphrase-fd 3;} 3>&0 |ssh -i $HOME/.ssh/auto $REMOTE_SERVER -l $REMOTE_USER

上記コマンドで使っている公開鍵。
no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty,command="umask 077; f=backup`date +%F-%H%M%S`.encoded; echo $f; cat >/home/hiroaki/backup/$f;" ssh-dss AAAAB3N (略)

command="" と no-pty を使って安全性を高められるのは良いんですが、出力先ファイル名がリモート側で生成されることが不便。環境変数 SSH_ORIGINAL_COMMAND を使うか、それとも他にもっと良い方法ないかなーと探している状態でした。でもこれで ssh + tar + gpg + SSH_ORIGINAL_COMMAND で問題なさそうとわかったのでこの方法を使うことにします。ありがとうございました。

mkfifo は思いつきませんでした。なるほど、これなら中間ファイルを作らないというのは実現できますね。名前付きパイプって使ったことありませんでしたが、いろいろ面白いことができそう。

- ssh を使ってるのに、なぜわざわざ gpg でファイルを暗号化するのか

何のために ssh 使ってるかわからないけど。

ssh は経路の安全性と認証の安全性を確保するため、gpg はファイルの安全性を確保するために使っています。2004-11-18 において背景を書かずに、「このご時世に外部にデータを持ち出すなら、通信の暗号化とファイルの暗号化は必須だと思う。」で済ませてしまったのは言葉が足りませんでした。

今回の件では、遠隔地のファイルバックアップ用サーバにデータを送ることを想定していました。

共用のサーバであれば、パーミッションが甘いと他の一般ユーザにファイルを見られてしまいます。そんな事態は論外ですが。私だけが使える専用サーバだとしても、遠隔地にあるので管理者権限を持った人間が現地にいます。悪意を持った管理者ならファイルを見ることができてしまいます。

また、万が一マシンが盗難などにあうと、盗んだ人間にもデータの中身を見られてしまいます。もちろん、盗難などに備えて、設備管理者は防犯対策を、システム管理者はファイルシステムの暗号化などの対策はやっておくべきです。同じように、一般ユーザである私にできることがあるならやっておこう、という意味で GPG を使ったファイルの暗号化を施しています。

セキュリティは各担当者の積み重ねの結果確保できるものであって、各担当者が手を抜いた場合、手を抜かれた箇所に依存する部分の安全性が揺らいでしまいますしね。

- 訂正

追記。やっぱり変なこと書いてた。リモートマシンで pgp したいのか。全然読んでなかったorz

なら上のスクリプトを実行後、

ssh user@hostname "(cd path && find . -type f -exec gpg options {} \;)"
でどうよ? gpg は使ってないので知らない。ので、オプションは適当に。 tar ファイルで送ったものを単に gpg したいなら(多分これがお望みの方法だろう)、

(cd path && tar cf - .) | \
ssh user@hostname "(cd path && gpg options > filename.tar.gpg)"
さらに圧縮したいなら、

(cd path && tar cf - . | bzip2 -9) | \
ssh user@hostname "(cd path && gpg options > filename.tar.bz2.gpg)"
でいい罠。

いえ、ローカルで暗号化しないとデータの安全性を確保しにくいので、暗号化はローカルでやって暗号化したデータのみを外部に送信したいところです。なぜ「リモートマシンで pgp したいのか」と解釈なさったんだろう? あ、なるほど。2004-11-18 の以下の部分ですね。

もちろんこれに gpg を組み合わせれば、転送後のリモートマシン上でのファイルの暗号化も実現できる。

確かにこれだと「リモートマシンで gpg を実行したいと」解釈できますね。表現が良くなかったので以下のように改めます。

「ssh/scp/sftp のみを使った場合はデータが暗号化されるのは通信経路上だけだが、gpg を組み合わせればリモートマシンに送ったあともデータを暗号化された状態に保つことができる。」

2004-11-18 (Thu)

* scp + tar + gpg で暗号化ネットワークバックアップ

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [シェルスクリプト] [バックアップ] [ssh] [gpg]

scp + tar + gpg で経路とファイルを暗号化したネットワーク・バックアップをおこなう。

- 要するに 2004-03-19 の「ftp + tar + gpgで暗号化ネットワーク・バックアップ」の置き換え

2004-03-19 に「ftp + tar + gpgで暗号化ネットワーク・バックアップ」という記事を書いた。この方法だとファイル自体は gpg によって暗号化しているので、中身を解読される可能性は低い。しかし、ftp を使っているため 経路上で ID と パスワードを盗聴されるおそれがある。ファイルの安全とアカウントの安全は別の問題だ。

無料ホームページサービスのように ftp のみのサービスしているホストの場合は盗聴に対して有効な対策をとるのが難しい。しかし、ssh をサービスしているホストなら scp や sftp を使うことで通信の暗号化を実現できる。

ssh/scp/sftp のみを使った場合はデータが暗号化されるのは通信経路上だけだが、gpg を組み合わせればリモートマシンに送ったあともデータを暗号化された状態に保つことができる。このご時世に外部にデータを持ち出すなら、通信の暗号化とファイルの暗号化は必須だと思う。

- scp 用の鍵作成

2004-11-17 の「ssh scp sftp の正しい自動実行方法」のやり方で scp 専用かつ権限を限定した鍵を作成。これを使う。

2004-11-22 追記。
2004-11-17 に書いた、command="" の指定がない公開鍵を使った場合は権限の限定が不十分。command="" を使わずに scp 専用の鍵としたいならば、ファイル転送に特化したシェルを使うなどの対策を講じないと結果的にシェルへのアクセスを許してしまうおそれがある。詳しくは 2004-11-22 「authorized_keys に書く no-pty と command="" の意味」を参照。

- scp は標準入力からデータを読んでくれない

2004-03-19 の「ftp + tar + gpgで暗号化ネットワーク・バックアップ」の利点の一つに、gpg が出力したデータを直接 ftp の標準入力に渡してアップロードする、というものがある。これのおかげで余計な中間ファイルを作らずに済む。

scp でも同じ事をしようと思ったのだが、なんと scp には標準入力からデータを読んで直接アップロードという機能がない。scp の man page を読んでみたが、代替の機能は見つけられなかった。仕方がないので一度ファイルに書き出すことにした。

scp man scp.0
http://www.unixuser.org/~euske/doc/openssh/jman/scp.html

- scp + tar + gpg で暗号化ネットワークバックアップするシェルスクリプト

というわけでできたのが以下のスクリプト。これを cron で自動実行する。

#!/bin/sh

# setup
PASS_PHRASE="MY SECRET PASS PHRASE STRING"
TAR_TARGET="/home/hiroaki/log.txt /home/hiroaki/etc /cygdrive/s/cvsroot"
OUTPUT_FILE="backup`date +%F-%H%M%S`.tar.bz2.encoded"
OUTPUT_PATH="/home/hiroaki/tmp/$OUTPUT_FILE"
REMOTE_SERVER=backup.example.com
REMOTE_USER=hiroaki
REMOTE_UPLOAD_DIR=/home/hiroaki/backup

date
echo $TAR_TARGET
echo $PASS_PHRASE | { tar --bzip2 -cf - $TAR_TARGET |gpg --batch -c --cipher-algo AES256 --force-mdc --passphrase-fd 3;} 3>&0 >$OUTPUT_PATH

echo output to $OUTPUT_PATH
scp -oIdentityFile=$HOME/.ssh/auto $OUTPUT_PATH $REMOTE_USER@$REMOTE_SERVER:$REMOTE_UPLOAD_DIR
if [ $? -ne 0 ]; then
  echo "`date` scp error" >&2
  exit 1
fi
rm -f $OUTPUT_PATH

echo backup complete
date

- scp では今回の目的には力不足

やっぱり標準入力から渡したデータをアップロードしたい。gpg の生成したファイルのハッシュをチェックしたり、scp以外のプログラムでも gpg の出力を利用したり、ローカルにもファイルをため込んだりしたい場合は一度ファイルに出力する方がいいのだが、今回はそんなことはしないし。

また、ファイルをアップロードした後にパーミッションを落としておきたいんだけど、scp では chmod などを発行できないようなのでそれもできない。umask を 077 にしておくだけじゃなくて、アップロードしたファイルに 600 を明示的に指定したいんだけどなあ。

scp コマンドがバージョンアップして機能が強化される見込みもなさそうだし。

OpenSSH FAQ
http://www.ie.openbsd.org/openssh/ja/faq.html#2.10
2.10 - scp に (なにかの機能) を追加してくれない?
短い答え: だめです。

長めの答え: scp は標準化されていないのです。それにもっとも近いものは「rcp が何をやるか」という仕様だけです。これは接続の両側で同じコマンドが使われるため、機能やオプションを追加すると異なる実装の間で相互運用できなくなる危険性があります。

新しい機能は sftp のほうが追加されやすいでしょう。なぜならこのプロトコルは標準化されていますし (まあ、 ドラフト標準ですが)、クライアントとサーバが別々になっているからです。

今回の目的には scp はあまり適していないようだ。明日は sftp を試してみよう。

2004-11-09 (Tue)

* GMail をバックアップストレージとして使う

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [Google] [メール] [シェルスクリプト] [バックアップ] [gpg]

GMail の 1GB という容量を生かして、バックアップストレージとして使う方法。

ストレージというと大げさな感じがするが、やってることは暗号化したアーカイブファイルを GMail にメール送信するスクリプトを書き、これを cron で一時間ごとに実行するだけ。GmailFS などを使ってファイルシステムとしてマウントするのも一つの方法だとは思うが、バックアップなんだから安定性重視でいきたいし、こういうのはシンプルな方がいい。

今日の戯言 ChangeLog 主にテキストファイルを gmail にバックアップ
http://apollo.u-gakugei.ac.jp/~sunaoka/clog/2004-11.php#2004 ...
主にテキストファイルを gmail にバックアップするつもりででっち上げてみたが,車輪の再開発のような気がしてならない.

1GB の容量を与えられたらそれを活用しようとする人はたくさんいるし、実装もたくさんあるようなので確かに車輪の再発明かもしれないですね。でも、自分好みの機能やインターフェイスにしたいなら、スクリプトを書いちゃう方が良いと思います。File::MMagic と Compress::Zlib を使って、テキストだったら圧縮するという機能は面白いと思いましたし。

- GMail をバックアップストレージとして使う - 私の場合

私の場合、シェルスクリプトで tar と gpg を呼び出して圧縮と暗号化をおこない、2004-10-092004-11-01 で書いた「添付ファイル付メールを送信する Ruby スクリプト」である samail で SMTP サーバに投げている。

送信先は GMail をはじめとするメールボックス容量に余裕のあるアドレス。メールなので数十メガバイトのファイルのバックアップという用途には適さない。ChangeLog メモのファイルや自分用 CVS リポジトリ、etc ディレクトリなど、小さなものだけをバックアップしている。Gmail のアカウントを取得する前は一日一回だったが、Gmail ができてからは一時間に一回に実行頻度を上げた。

内容にもよるが、外部にデータを持ち出すなら暗号化は必須だと感じている。GnuPG を使えばフリーで強力な暗号を利用可能。具体的には 2004-01-08 で書いた「gpg で標準入力からパスワードを渡してバッチ処理で暗号化」を利用し、GPG の共通鍵暗号で暗号化している。

暗号化アルゴリズムには AES256 (256bit Advanced Encryption Standard) を指定。gpg のデフォルトの CAST5 でも良いと思うけど、AES は NIST (National Institute of Standards and Technology 米国商務省技術標準局) 御用達の暗号化アルゴリズムとのことなので、これを使うことにした。

Perl だったら Crypt::CAST5 や Crypt::Rijndael とか使うのが一般的なのかな?

#!/bin/sh

# gmail_backup.sh
# Archiving, Crypting, and mail sending script
# Copyright (C) 2004 Saito Hiroaki <sonic64@infoseek.jp>
# http://sonic64.com/

# setup
PASS_PHRASE="MY SECRET PASS PHRASE STRING"
TAR_TARGET="/home/hiroaki/log.txt /home/hiroaki/etc /cygdrive/s/cvsroot"
OUTPUT_PATH="/home/hiroaki/tmp/backup.tar.bz2.encoded"
to_address="to@example.com, to@gmail.example.com"
optional_adderss="to@daily.example.com"
from_address="from@example.com"
smtp_server="smtp.example.com"


date
echo $TAR_TARGET
echo $PASS_PHRASE | { tar --bzip2 -cf - $TAR_TARGET |gpg --batch -c --cipher-algo AES256 --force-mdc --passphrase-fd 3;} 3>&0 >$OUTPUT_PATH

echo output to $OUTPUT_PATH
echo archiving complete

if [ `date +%H` -eq 23 ]; then
  to_address="$to_address $optional_adderss"
fi

/usr/local/bin/ruby /home/hiroaki/script/samail -v --to "$to_address" --from $from_address --smtp $smtp_server --subject "[GMail Backup] `date +%c`" --attachment $OUTPUT_PATH

date
echo mail send complete

以前は暗号化した圧縮ファイルの md5 ハッシュを取っておいて、前回と異なったときのみメール送信という動きにしていたが、その機能は外してしまった。そういう意味では一度ファイル出力せずに直接 samail の標準入力に渡した方がシンプルだな。よし、samail の次のバージョンでは標準入力から読み込んだデータを添付ファイルとして送信できるようにしよう。

- gmail_backup.sh の設定方法

# setup のところに設定を書く。
PASS_PHRASE に gpg に渡すパスフレーズ、TAR_TARGET にバックアップしたいファイルやディレクトリのパス、OUTPUT_PATH に暗号化した圧縮ファイルの出力先を記述。あとは To と From と SMTP サーバ名を書いて完了。Ruby のパスを /usr/local/bin/ruby と samail のパスを /home/hiroaki/script/samail とハードコーディングしてるのはあまり良くないかも。

私の場合 cygwin ネイティブのファイルシステムと /cygdrive の両方にバックアップしたいファイルがあるため、/ からフルパスで TAR_TARGET を記述している。このせいで tar に以下のようなメッセージを表示されるけど、実害がないので問題ないだろう。
tar: Removing leading `/' from member names

- GMail 側の設定

Gmail といえども 1GB しか容量がないので、古いバックアップファイルは削除する必要がある。Gmail の Trash ディレクトリは 30日過ぎると削除されるという性質があるので、これを利用する。この性質は Trash を開いたときに出るメッセージに書かれていた。
Note: Trashed messages more than 30 days old will be automatically deleted.

メール送信時に Subject に特徴的な文字列を入れておき、その文字列でフィルタリング。マッチしたメールは自動的に Trash 行きになるように設定する。こうすることで「30日を過ぎたバックアップファイルは自動的に削除」を実現できる。

- メール送信の頻度はどれくらいがよいか

これはもうお好みで良いと思う。一日一回くらいでも充分なんじゃないかと思うが、せっかく容量があるんならいっぱい送っちゃえ、ということで一時間に一回にしている。

一回 1MB のファイルを送るとして、1MB * 24時間 * 30日 = 720MB 、Base64 すると 3分の4倍くらいになるので、それを含めても 1MB * 24時間 * 30日 * 4 / 3 = 960MB。24時間稼働のマシンでなければ頻度はもっと減るし、一日一回にしておけばさらに余裕。ところで、GMail って添付ファイルは Base64 デコードした状態でファイルサイズを計算している気がするんだけど気のせいかな。

- 一日一回だけ別のアドレスを追加して送信

このスクリプトは cron で一時間ごとに起動しているが、23時台に起動したときだけ optional_adderss にセットされた送信先を追加している。Gmail ほどメールボックス容量に余裕がないアドレスなので、一日一回だけの送信にしたいからだ。Gmail の予備として使っている。

if [ `date +%H` -eq 23 ]; then
  to_address="$to_address $optional_adderss"
fi

- 分割すれば巨大ファイルでも OK?

分割すれば数十メガバイト単位の巨大ファイルでもバックアップできるが、いざリストアしようと思ったときに分割したメールを連結するという手間をかけたくない。標準で POP で受信できない場合はなおさら。そういう巨大ファイルは他の方法を使うべきでだ。どうしてもネットワーク経由でのバックアップがしたいなら、2004-03-19 で書いた「Linux: gpg: ftp: ftp + tar + gpgで暗号化ネットワーク・バックアップ」などが使えるかもしれない。

- 正常に復号して圧縮ファイルを展開できるかどうかのテストを忘れずに

バックアップしただけで安心してはいけない。いざという時にに迅速にリストアできなければ意味がない。私は以下のようにして復号と圧縮ファイルの展開をしている。

$ echo "MY SECRET PASS PHRASE STRING" |gpg --passphrase-fd 0 -o - backup.tar.bz2.encoded |tar -x --bzip2
Reading passphrase from file descriptor 0
gpg: AES256 encrypted data
gpg: encrypted with 1 passphrase

bzip2: (stdin): trailing garbage after EOF ignored

--force-mdc オプションなしで暗号化したファイルの場合、以下のメッセージが表示されるかも知れない。これについては私も詳しくないので言及しない。とりあえず --force-mdc を付ければ警告は出なくなる。
gpg: WARNING: message was not integrity protected

bzip2 の警告は、末尾になにか余計なデータがあるので無視するよ、というもの。理由は不明。tar の出力を直接 gpg の標準入力に渡しているから?

- 「フッフッフッフッフッフッ まぬけめ! Gmail」「や…やろう まさか!」「きさまのおかげで ストレージ利用がしやすくなったぞッ!」

追記。Gmail が POP3 をサポートするとのこと。

ITmediaニュース:GmailがPOP3サポート、ウイルス対策も提供へ
http://www.itmedia.co.jp/news/articles/0411/11/news010.html

これでさらにストレージとして利用するのが簡単になった。そのうち 読み書き用の API を書く人も出てくるだろうな。POP/SMTP ベースだと遅延があるのでリアルタイム性を要求するアプリケーションには使えないだろうけど、用途を選べば充分使える。

2004-08-03 (Tue)

* SQL Server バックアップ時のエラー 15457

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [MS SQL Server] [バックアップ]

トランザクションログを一時間間隔でバックアップするように設定したあと、イベントログに「情報」レベルのメッセージが記録されていた。気になったので D:\sqldata\MSSQL\LOG を確認したところ、以下の行が存在していた。
2004-08-03 16:47:35.41 spid54    エラー : 15457、レベル : 0、状態 : 1
2004-08-03 16:47:35.41 spid54    設定オプション 'show advanced options' が 1 から 1 に変更されました。RECONFIGURE ステートメントを実行して、インストールしてください。。

Books Online を読む前に、Google で 15457 SQL Server を検索するとヒット。
MSrepl_commands
http://www.sql-server-performance.com/forum/topic.asp?ARCHIV ...
Error 15457 are informational messages and not really error messages, if you change server properties then you will see this message. When using SP_CONFIGURE statement the message will be issued to run RECONFIGURE, refer to BOL for more information.

要するに設定変更したよというメッセージでしかないわけだ。エラーじゃないなら無視するようにしよう。

2004-05-18 (Tue)

* バックアップを Enterprise Manager からリストア

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [MS SQL Server] [バックアップ]

SQL Server からダンプしたファイルを Enterprise Manager を使って別のマシンにリストアするときの手順。

バックアップを取得したサーバと復元するサーバが同一の場合は、リポジトリにバックアップの一覧が表示されるためもう少し簡単になる。しかし、本番サーバのバックアップを開発環境でリストアするときなどは以下の手順が必要。

SQL Server Books Online バックアップ デバイスからバックアップを復元する方法 (Enterprise Manager)
バックアップ デバイスからバックアップを復元するには

1. サーバー グループを展開し、サーバーを展開します。


2. [データベース] フォルダを展開し、データベースを右クリックして、[すべてのタスク] をポイントし、[データベースの復元] をクリックします。


3. [データベースとして復元] ボックスで、復元するデータベースの名前が既定の名前と異なる場合は、名前を選択するか入力します。データベースを新しい名前で復元する場合は、新しいデータベース名を入力します。

注  データベースに新しい名前を指定すると、データベース バックアップから復元されるデータベース ファイルの新しい名前が自動的に決まります。

4. [デバイスから] をクリックし、[デバイス選択] をクリックします。


5. [復元元] ボックスの [テープ] または [ディスク] をクリックし、復元元のデバイスをクリックします。
デバイスが表示されない場合は、[追加] をクリックして既存のバックアップ デバイスを追加するか、または新しいバックアップ デバイスを作成します。[データベースの復元] ダイアログ ボックスで、[内容表示] をクリックし、復元するバックアップ セットをクリックします。

以下略。

- リストア後の注意点

2003-09-09 の「データベースのリストアでユーザ情報が壊れる」で触れた不具合に注意。
「274188 - [SQL]PRB: 対応するログインの存在しないユーザー」
http://support.microsoft.com/default.aspx?scid=kb;JA;274188
対応するログインの存在しないユーザーに関する問題の解決手順

上記手順で確認した対応するログインの存在しないユーザーに関して、次のコマンドを実行します。
    Use Northwind
    go
    sp_change_users_login 'update_one', 'test', 'test'

これは、サーバー ログイン "test" を Northwind データベース ユーザー "test" に再度関連付けます。sp_change_users_login ストアド プロシージャを "auto_fix" パラメータとともに実行することで、対応するログインの存在しないユーザーすべてを更新することもできます。しかし、これは推奨されません。なぜなら、SQL Server は名前によってログインとユーザーを一致させようとするからです。ほとんどの場合には、これは期待したとおりの結果になります。しかし、誤ったログインがユーザーに関連付けられた場合、ユーザーは不正な権限を持ってしまいます。

文法は以下の通り。
sp_change_users_login 'update_one', '@UserNamePattern', '@LoginName'

2004-03-19 (Fri)

* ftp + tar + gpgで暗号化ネットワーク・バックアップ

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [Linux] [gpg] [ftp] [バックアップ]

ftp を使ったネットワークバックアップについての記事を 2003-12-01 に書いた。この手法の欠点の一つは、暗号化されないことだ。ftp に暗号化機能がないので仕方がないが、他のツールを組み合わせれば、暗号化できる。

- 何を暗号化するか

暗号化には通信経路上の暗号化とファイルの暗号化がある。通信経路上の暗号化だと、バックアップ先サーバへたどり着いた後のファイルは生のままになる。ファイルの暗号化だと、バックアップ先サーバに到達した後もファイルはずっと暗号化されたままだ。

通信経路の暗号化とファイルの暗号化のどちらが良いかは場合による。もちろん両方やっても良い。バックアップ先が共用のファイルサーバで、そのサーバの管理者を含め、自分以外のユーザがアクセスする可能性があるなら、ファイルそのものを暗号化したほうがいいだろう。

一方、バックアップ先が自分しかアクセスしないサーバだったら、通信経路上だけを暗号化してファイルを生で保存しておいた方が便利だろう。いざディスクがクラッシュして復旧しようとしているのに、暗号化解除のパスワードがわからない、といったトラブルも防げる。また、ファイルを暗号化しただけでは ftp のアカウントのパスワードが生のままネットワーク上を流れてしまうが、通信経路自体を暗号化すればこれも解決できる。

- 通信の暗号化

通信の暗号化を組み合わせたネットワークバックアップは、やったことがないのでとくに書かない。ssh、scp、sftp を使ったり、VPN を使ったり、方法はいくらでもあると思う。一応 ssh を使ったやり方について記事を見つけたのでメモしておく。

Q. cron 等から起動されるバッチ処理の中で ssh を利用したいのですが、ログインを自動化するにはどうすればよいですか?
http://www.jp.freebsd.org/QandA/HTML/2255.html

- ファイルの暗号化

暗号化できるならどんなツールでもいいが、今回の用途で使うならば、自動化ができて、強い暗号強度を持ち、無償で利用できるものがいい。この条件を満たす暗号化ツールとしては gpg がある。2004-01-08 に書いた「gpg: ファイルをパスワード/パスフレーズだけで暗号化/復号する」や「gpg: 標準入力からパスフレーズを渡してバッチ処理でファイルを暗号化」が参考になるだろう。

tar の出力を gpg に通して暗号化してやればいいのだが、私が使っている ftp コマンドは送信ファイル指定部分にパイプを使ったコマンドラインを記述できないようなので、該当部分はシェルスクリプトにした。

以下のようなスクリプトを用意して、tar で固めたデータを暗号化して出力できるようにする。
#!/bin/sh

PASS_PHRASE="passphrase"
TAR_TARGET="script etc"
BASE_DIR=/home/hiroaki

echo $PASS_PHRASE | { tar -C $BASE_DIR -zcf - $TAR_TARGET 2>/dev/null |gpg --batch -c --passphrase-fd 3;} 3>&0

これを 2003-12-01 の ftp バックアップスクリプトで呼ぶだけだ。tar で出力したファイルを暗号化しているので、拡張子に .gpg を付けている。
ftp -i -v -n 10.39.38.89 << END
user USER_ID PASSWORD
cd /d/backup
bin
put |/home/hiroaki/script/hgpg.sh "backup_`date +%a`.tar.gz.gpg"
quit
END

gpg 自体が圧縮機能を持っているので、gzip する必要性は薄いかもしれない。そのあたりはお好みで。

2003-12-01 (Mon)

* ftp + tar + cron で自動ネットワーク・バックアップ

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [Linux] [ftp] [バックアップ]

ftp コマンドには、標準入力から読ませたデータに好きなファイル名を付けてアップロードする機能がある。これを利用してネットワークバックアップスクリプトを作成する。スクリプトを毎日 cron で回せば、リモートマシンに毎日バックアップを自動で ftp アップロードすることができる。

- ftp + tar によるバックアップの長所と短所

ftp + tar を使ったバックアップの長所は、どちらも unix システムなら標準でインストールされているコマンドなので、ツールのインストールが不要で設定が超簡単なことと、ネットワーク経由のバックアップなので外部マシンにデータを持っていくことが楽なことだ。短所は、ネットワーク経由のバックアップなので帯域が細い環境では使いにくいかもしれないこと、ftp アカウントが必要なこと、暗号化されないこと、ftp アカウントをシェルスクリプト中に埋め込まなければならないことだろうか。

暗号化については、tar の出力を gpg に通したり、scp や sftp を利用すれば解決できる。2004-03-19 に「ftp + tar + gpgで暗号化ネットワーク・バックアップ」という記事を書いた。 ftp + tar + gpg の利用について解説とサンプルスクリプトがある。

- バックアップで一番大切なこと

バックアップで一番大切なことは、バックアップすることだ。手間がかかるからといってやらないでいる時に限ってトラブルがやってくる。だから、とにかくまず手間がかからなくてシンプルな方法を考えよう。rsync や samba を使ったり、pdumpfs や afio や ArcServe などのバックアップツールを使った方法もある。tar + ftp よりも他の方法を使った方が楽にバックアップシステムを構築できるなら、迷わず楽な方を使った方が良い。とにかくまずバックアップすることが大切だ。

- ftp にコマンドの出力結果をアップロードさせる

冒頭にも書いたが、ftp コマンドには標準入力の内容をアップロードする機能がある。これを利用してバックアップスクリプトを作成する。以下、man ページから引用。

Manpage of FTP
http://www.linux.or.jp/JM/html/netkit/man1/ftp.1.html
ファイル名の変換
ftp の引き数として指定されたファイル名は、以下の規則に従って変更される。

1. ファイル名として `- ' が指定された場合、(読み込みとして) stdin が、(書き出しとして) stdout が使われる。
2. ファイル名の最初の文字が `|' の場合、残りの引き数はシェルコマンドとして解釈される。そして、 ftp は与えられた引き数を popen(3) に渡してシェルを fork し、stdout を読み込み、stdin に書き出す。シェルコマンドがスペースを含む場合、 " ls -lt" のように引き数をクォートしなければならない。この機構の特に役立つ例としては、dir more がある。

- バックアップスクリプトの例

tar から標準出力に出力した内容を ftp が標準入力で受けてアップロードする。ファイル名に曜日を使っているので、7世代までバックアップが残る。ファイル名に日付を使えば、一か月前まで残せる。
#!/bin/sh

# log setting
LOGDIR=/var/log
LOG=$LOGDIR/ftpbackup.log
LOG_TAR=$LOGDIR/ftpbackup_tar.log

echo `date` backup start >>$LOG
echo `date` backup start >>$LOG_TAR

# ftp and tar backup start
ftp -i -v -n 10.3.31.89 << END >>$LOG
user USER_ID PASSWORD
cd /d/backup
bin
put |"tar -C / -zvcf - etc home --exclude=music --exclude=backup 2>>$LOG_TAR" "`hostname`_`date +%a`.tar.gz"
quit
END

echo `date` backup complete >>$LOG_TAR
echo `date` backup complete >>$LOG

- 解説

以下ではコマンドのオプションや使われ方を解説する。細かく書いたので長い。必要なところだけ読んでほしい。

ftp -i -v -n 10.3.31.89 << END >>$LOG
-i オプションはバッチ処理のために、-v はログに詳細を記録するために、-n は .netrc ファイルを使用せずに ftp サーバへのログインに使用するパスワードを指定するためにここで指定している。10.3.31.89 は今回使用した ftp サーバ名。

-i
複数のファイルの転送中に対話 (interactive) プロンプトを出さないようにする。

-v
詳細表示 (verbose) オプションを使うと、 ftp はデータ転送の結果だけでなく、リモートサーバからの全てのレスポンスを表示する。

-n
ftp が最初の接続で 自動ログイン (auto-login) しようとするのを抑制する。自動ログインが可能な場合、 ftp はユーザーのホームディレクトリにある .netrc ファイル ( netrc(5) を参照) でリモートマシンのアカウントが記述されているエントリをチェックする。エントリがない場合、 ftp はリモートマシンのログイン名 (デフォルトではローカルマシンでログイン名) を要求するプロンプトを出す。必要ならば、ログインに使うパスワードとアカウントを要求するプロンプトを出す。

<< END は、次に END が出てくるまでに記述された内容を、ftp コマンドに渡すためのリダイレクト。>>$LOG は ftp コマンドの結果を $LOG に追記する。

user USER_ID PASSWORD
cd /d/backup
bin
USER_ID に ftp サーバにログインするための ID を指定、PASSWORD にパスワードを指定。例を挙げておこう。ID が operator で パスワードが backup_command なら、
user operator backup_command
とすればよい。その後はログイン後に実行させるコマンドを列記する。私が使っているサーバではバックアップファイルをアップロードするディレクトリが /d/backup なので、cd コマンドでディレクトリを移動。その後転送モードをバイナリモードに明示的に変更。

put で始まる行がこのスクリプトの要となる部分。
put |"tar -C / -zvcf - etc home --exclude=music --exclude=backup 2>>$LOG_TAR" "`hostname`_`date +%a`.tar.gz"
まず put コマンドでファイルをアップロードする。ただし、put の第一引数は | で始まっているので、アップロードする中身はファイルではなく "" で囲まれた tar コマンドが出力したものとなる。"" で囲まれた部分はパイプを使ったコマンドラインは記述できないようだ。パイプを使った複雑なコマンドラインを書きたい場合は、シェルスクリプトにすればいい。

tar の部分を解説しよう。
"tar -C / -zvcf - etc home --exclude=music --exclude=backup 2>>$LOG_TAR"
まず -C で tar を実行するディレクトリを / に移動し、その中の etc ディレクトリと home ディレクトリをバックアップ対象としている。ただし、music または backup という名のファイルやディレクトリはバックアップ対象から除外する。-z が指定されているのでこれらを gzip で圧縮し、-f - が指定されているので圧縮結果を標準出力に出力している。2>>$LOG_TAR の部分は、tar コマンドの標準エラー出力への出力結果を $LOG_TAR に追記している。tar は標準エラー出力に詳細を出力するので、それを受けてログに書いているというわけだ。

以下の部分は put コマンドの第2引数として扱われる。
"`hostname`_`date +%a`.tar.gz"
put は第2引数でアップロード先にどんなファイル名で格納するかを指定できる。ここでは、 hostname コマンドの出力結果と date +%a コマンドの出力結果を利用している。date +%a は現在の曜日を返す。よって、マシン名が sonic で 今日が火曜日だとすると、最終的なファイル名は sonic_Tue.tar.gz となる。ehco で表示させるとわかりやすいかな。
[hiroaki@sonic ~]$ echo `hostname`_`date +%a`.tar.gz
sonic_Tue.tar.gz

2003-10-27 (Mon)

* DB サーバのバックアップファイルのローテーションと圧縮

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [Linux] [バックアップ]

毎日 MS SQL Server からデータをダンプしたものを ftp でバックアップサーバに転送してはいるが、ファイル名が同じなので毎回上書きされてしまう。ちょっと怖いので、一週間でローテーションすることにした。
compress オプションも追加。一日で 80MB 弱のサイズだから、ちょっとでも小さくしたい。
そもそも MS SQL Server は圧縮してくれてないようだし。

試しに gzip -9 kessandb_current_sql_server_backup してみたら、80MB が 12MB まで縮んだ。
実際は gzip じゃなくて compress をだったり、圧縮レベルも違うかもしれないけど。

ということで、以下を /etc/logrotate.d/sqlserver_backup として作成。
/home/hiroaki/backup/example_db_current_sql_server_backup {
    daily
    rotate 8
    compress
    nocreate
}

2003-10-14 (Tue)

* Linux マシン pro の /dev/hda のバックアップと換装

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [Linux] [バックアップ]

pro の /dev/hda の調子が悪い。
3.5 GB よりも後ろの部分あたりに書き込もうとすると、IDE デバイスだかなんだかがそのまま無反応になってしまい、コンソールに延々とエラーメッセージが表示されるという状態になる。このまま使い続けるのは怖いので、ハードディスクを交換することにした。交換するドライブは /home が入っている。以下では、データの移行について調べたこと、試したことを記録する。

- やりたいこと

/home パーティションなので、新しいディスクにデータを全部引き継ぎたい。さてどうするか。

- 環境

OS: TurboLinux 6.5 Server

- /dev/hda について

$dmesg |grep hda
hda: Maxtor 84320D5, ATA DISK drive
hda: Maxtor 84320D5, 4119MB w/256kB Cache, CHS=525/255/63

$ df -h
/dev/hda1            4.0G  2.5G  1.3G  65% /home

ちょうど一台使われていないマシンがあるので、そのマシンに 84320D5 と 新しいドライブを接続し、knoppix を使ってコピーするとしよう。コピーは単純に cp -r でいいかな。この方法でファイルオーナーやパーミッションが引き継がれれればいいんだけど。

・・・と思ったけど、tar でやるのが楽なようだ。
[linux-users:58294] Re: HDD まるごと複製
http://search.luky.org/linux-users.5/msg07977.html

tar -c -l -S -f - / | (cd /newroot && tar -x -v -f -)
-c, --create 新しいアーカイブを作成する
-l, --one-file-system ローカルなファイル・システムに限定してアーカイブを作成する
-S, --sparse 疎らなファイルを効率的に処理する
-f, --file [HOSTNAME:]F Fというアーカイブ・ファイルまたはデバイスを使う(デフォルトは/dev/rmt0)

-f - がよくわからない。付けても付けなくても変わらなかった。もしかして、標準出力を意味するのだろうか?

() で括ってそこに 標準出力をパイプできるなんて初めて知った。もっとも、tar には -C, --directory DIR DIRにcdしてから動作を行なう があるから、-C を使ってもいいかも。

パーミッションとオーナーも同じにしたいが、
以下の報告があったため tar のマニュアルを確認してみた。
[linux-users:58424] Re: HDDまるごと複製
http://search.luky.org/linux-users.5/msg08107.html
> >  tar -c -l -S -f - / | (cd /newroot && tar -x -v -f -)
>
> これでやったわけですが、私は結局遠隔にあるコピー元?にログインして
> 一旦 tarball をつくって、それをダウンロードして手元で複製、という
> 工程になったので、標準入出力を使う上記方法にはならなかったのですが、
> 少なくとも一旦 tarball を作ってからの場合だと、復元の再に -p オプションも
> ないとだめのようです。パーミッションが狂ってしまって慌てました。

以前この ML で tar では symlink の owner.group が復元されないという
話がありましたが、大丈夫ですか?
正しく復元できたのでしたら、使用された tar の option, version を教えて
ください。

# cpio なら symlink の owner もちゃんと復元されるのですが、hard link
  の保存方法がわからなくて挫折。
  今は tar で full backup 取って、戻す時は tar xpf ... のあと / で
  ls -lR しておいたログを元に chown してまわっています。
  symlink の owner なんてどうでも良いと以前は思ってましたけど、apache
  で SymLinksIfOwnerMatch 使うようになってからは...

上記報告を踏まえ、
ファイルオーナーとパーミッションを同じにするため以下のオプションを付けてみることにした。
--same-owner アーカイブ内のファイルのものと同じ所有属性でファイルを抽出する
-p, --same-permissions, --preserve-permissions 許可情報を全て抽出する

- 最終的に実行するコマンド

tar -c -p -l -S -f - / | (cd /newroot && tar -x -v -p --same-owner -f -)

- Hard Disk Upgrade Mini How-To 7. 元の HD から新しい HD へのファイルのコピー

http://www.linux.or.jp/JF/JFdocs/Hard-Disk-Upgrade/copy.html
に気になる記述がある。シンボリックリンクのオーナーの件だろうか・・・?
この Mini How-To の以前のバージョンではハードディスクをコピーするのに
tar コマンドも使えると書きましたがこの方法にはバグがあります。

- いざ環境作り

結局 knoppix はブートしなかった。
Uncompressing Linux... Ok, booting the kernel.
で止まってしまう。
http://www.dnsbalance.ring.gr.jp/archives/linux/knoppix/iso/ の knoppix_20030924-20031002.iso でもダメ。

仕方がないので、手元にあった debian woody 3.0 の CD でブートさせた。シェルを起動し、woody のインストーラでパーティションを切る。ディスク丸ごと1パーティションにした。次に、
# mke2fs -m 0 -cc -T news
でフォーマット。ロッカーに転がってたディスクなので、不良セクタがあるおそれがある。不良ブロックを検査 をするために、-cc で read-write test を実行するように指定した。

また、-m 0 オプションを付けて root 用の予約領域をゼロにした。これは、以下の情報を元にやってみたことだ。

Debian GNU/Linux スレッド Ver. 19
http://pc.2ch.net/test/read.cgi/linux/1065374560/193
http://pc.2ch.net/test/read.cgi/linux/1065374560/197
http://pc.2ch.net/test/read.cgi/linux/1065374560/200
193 :login:Penguin [sage] :03/10/15 21:52 ID:bLLfhwtE
ext3 な /home の空きが少なくなってきたので悪足掻きに

tune2fs -m 0 /dev/hoge

で reserved-blocks を無くした。sid で一般ユーザでやると

% /sbin/tune2fs -m 0 /dev/hda8
tune2fs 1.35-WIP (21-Aug-2003)
/sbin/tune2fs: 許可がありません while trying to open /dev/hda8
Couldn't find valid filesystem superblock.

とエラーが出るんだけど、woody だと一般ユーザでも出来ちった…

% /sbin/tune2fs -m 0 /dev/hda11
tune2fs 1.27 (8-Mar-2002)
Setting reserved blocks percentage to 0 (0 blocks)

そ、そーゆーもんなん?(;´Д`)

197 : [sage] :03/10/15 22:33 ID:i5NBqHn0
>>193
予約領域ってゼロにしても大丈夫なのかな。

200 :login:Penguin [sage] :03/10/16 00:50 ID:kXslWQqp
>>197
rootは/home一杯になっても別に困らんから。

- mke2fs -cc って長いよ・・・

4GB のマシンで、仮想コンソールが2つあったので2台のドライブを同時並行でフォーマットしてみた。

- 実際の作業

コンソールでの作業だったため、文中のエラーメッセージは正確ではないので注意。もしかしたら入力したコマンドも実際のものと違っているかもしれない。

まず2台のディスクを移設用マシンに接続し、woody の CD-ROM でブートさせる。ALT + F2 でコンソールに切り替え、各ドライブをマウントする。/bin/cp -a でファイルを全部コピーする。今回は /home しかコピーしないので、これが一番簡単。
# /bin/cp -af /mnt/old/* /mnt/new

コピーが完了したら、新しいドライブを本番マシンに接続。本来ならばこれで作業が終わるはずだったが、ブートローダが起動しないという状況に見舞われた。完全に忘れていたが、今回の対象ドライブは /dev/hda である。ブートローダをインストールしなければならない。

woody の CD には lilo が入っているが、lilo を実行しようとすると、/target にルートファイルシステムをマウントしないと使えないよ、といったエラーメッセージが出てしまう。いくつか試行錯誤をしてみたがうまくいかない。ライブラリのバージョンが違う、といったエラーメッセージまで出てしまう。元のシステムは TurboLinux 6.5 Server であるため、整合性がとれないのだろうか? /sbin ってスタティックリンクしてるからライブラリは関係ないんじゃないか? と思っていろいろ試そうとしたが、諦めて TurboLinux 6.5 Server の CD-ROM でブートすることにした。ところが、今度はなんと lilo がない。/sbin にも /usr/sbin にもない。

CD に無くても、/dev/hdb に入ってるルートファイルシステムにあるじゃんと途中で気づき、/dev/hdb2 をマウントしようとするが、なんだかうまくマウントできない。これも当たり前で、/dev/hdb2 は swap パーティションだったのだ。 気づけば単純なことだが、無機質で乾燥したマシン室では注意力が落ちるということを、身をもって知らされた。ちなみに、/dev/hdb1 は /boot だ。

ルートファイルシステムをマウントし、lilo を実行。
/mnt/tmp/sbin/lilo -C /etc/lilo.conf
しかし、これでもうまくいかない。/boot/boot.b が無いとかいうエラーメッセージが出る。無ければコピーしてしまえ、ということで、
cp /mnt/tmp/boot/* /boot
を実行したが、今度は 0x100 なんてデバイスは知らないよ、といったメッセージが出る。

ここで一度 lilo について調べた方が良い気がしたので、JM で lilo の man を見る。すると、
-r root-directory 操作を行う前に、 chroot でルートディレクトリを変更する。
というオプションがあることに気づいた。これを指定してやればいいんじゃないか、と思い実行するとうまくいった。最終的に実行したのは、以下のコマンドだ。
/mnt/tmp/sbin/lilo -r /mnt/tmp -C /etc/lilo.conf

無事ブートローダのインストールが終わり、ドライブ換装作業は完了。pro は今快調に動作している。後で耐久テストでもやってみることにしよう。

2003-09-17 (Wed)

* Partimageに関する覚え書き

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [Linux] [バックアップ]

http://buxus.s31.xrea.com:8080/pukiwiki/pukiwiki.php?%5B%5Bp ...
パーティションをまるごとバックアップするツール。
ネットワーク越しにバックアップすることもできる。
パーティションは unmount してある必要があるけど。

2003-08-26 (Tue)

* SQL Server のトランザクションログの運用

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [MS SQL Server] [バックアップ]

トランザクションログがいっぱいになると、その時点で DB が停止する。
今回のプロジェクトではどのような運用が望ましいのかを調査。

- フルバックアップで十分。

今回のプロジェクトで使用している SQL Server では、毎日 2:30 に DB のフルバックアップを取得している。この時点で前回バックアップからのトランザクションログを破棄してしまって構わない。また、トランザクションログのサイズの見積もりは、以下のようにして行う。

[SQL:02744] Re: トランザクションログの見積り
http://www.users.gr.jp/ml/archive/sql/2744.asp

現在のトランザクションログサイズは、814MBだ。これだけあれば十分だろう。

2003-05-26 (Mon)

* ChangeLog メモのバックアップ

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [ChangeLog メモ] [バックアップ]

/home/hiroaki/backup/changelog に5分おきにバックアップを取っている。
ファイル数が2000個近くになっていた。
$ ls -l /home/hiroaki/backup/changelog |wc
1975 17768 165828

一週間以上経ったものは find で探して rm しているが、それでも2000個。多すぎだろう。
内容が変化していないのに5分おきにバックアップを取るのは非効率だ。
前回のファイルの md5 を求めて、現在のファイルの md5 と比較し、
違っていたらバックアップと html 出力を行うようにすればいいかな。
追記: 2003-06-06 で実装した。

2003-04-17 (Thu)

* Postgres バックアップスクリプト version 1.1

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [Postgres] [バックアップ]

postgres の pg_dump のデータが溜まりすぎて、DAT にバックアップできなくなっていた。
2002-09-11 に書いた Postgres バックアップスクリプトに n 日以前のファイルを消すという処理を追加し、以下のようにした。また、バックアップ対象 DB を psql -l から取得するようにした。

pg_dumpall を使っていないのは、ラージオブジェクトを扱うためと、データベース毎にバックアップファイルを分けたかったから。

動作を確認した環境は PostgreSQL 7.2.1 + TurboLinux 6.5 Server だ。凝ったことはしていないので、バージョンが異なっても動くはずだ。cron に仕込んで夜間バッチなどで動かすときは、postgres 関連コマンドやディレクトリへのパスを設定するのを忘れずに。以下のスクリプトでは、 # Setting の部分で 環境変数を設定している。

#/bin/sh

# PostgreSQL database backup script
# Version 1.1 [Apr. 17, 2002] Add routine: deleting exipired files.
# Version 1.0 [Sep. 10, 2002] First release.
#  Saito Hiroaki  <example@example.com>

# * Feature
# Dump to DATABASE_NAME_YYMMDD.pgdmp.
# Delete expired pgdmp file.
# Output log.

# Setting
PATH="$PATH":/usr/local/pgsql/bin
PG=/usr/local/pgsql
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH":$PG/lib
export PGLIB=$PG/lib
export PGDATA=$PG/data

# Get all DB name
TARGET_DB=`psql -l -P format=unaligned -P fieldsep=, -P tuples_only |perl -F, -lane "if (@F[0] ne 'template0') {print @F[0]}"`

DIR=/home/postgres
LOG=$DIR/pgdump.log
BACKUPDIR=$DIR/dbbackup
EXPIRE_DAY=90

# Main routine
echo "pg_dump start." `date` >>$LOG
date=`date +%Y%m%d`

for db_name in $TARGET_DB
do
  DUMP_FILE_PATH=$BACKUPDIR/${db_name}_${date}.pgdmp
  /usr/local/pgsql/bin/pg_dump $db_name -b -o -Fc > $DUMP_FILE_PATH 2>>$LOG
  echo "Database $db_name backup complete." `date` >>$LOG
done

echo "pg_dump complete." `date` >>$LOG

echo "Delete expired pgdmp file start." `date` >>$LOG
find $BACKUPDIR -type f -daystart -mtime +$EXPIRE_DAY |xargs /bin/rm -f
echo "Delete expired pgdmp file complete." `date` >>$LOG

私はこのスクリプトを postgres スーパーユーザの crontab に仕込んで毎日実行している。postgres スーパーユーザ以外で動かすこともできるとは思うが、データベースにアクセスするためにパスワードを要求されたりするかもしれず、いろいろ手間がかかりそうな予感。管理者権限を使いたくないという意見もあるかもしれないが、バックアップというのは本来管理者やオペレータが行う作業だし、素直に postgres スーパーユーザで実行してしまった方が楽だ。

「一般ユーザとして全部のデータベースをバックアップする」という状況ってあまり考えられない。どうしても管理者権限を使いたくないなら、以下のオプションを使ってできるんじゃないかと思う。試してないけど。
-U, --username=NAME      connect as specified database user
-W, --password          force password prompt (should happen automatically)

2002-09-11 (Wed)

* Postgres 自動バックアップスクリプト

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [Postgres] [バックアップ]

- 2003-04-17 追記

このスクリプトの改訂版を 2003-04-17 Postgres: Postgres バックアップスクリプト version 1.1 に書いた。

pg_dump を使ってデータベース毎にバックアップを取るシェルスクリプト。
要するに pg_dump を シェルの for 文で回してデータベースの個数分作成しているだけ。
バックアップファイルは YYYYMMDD.pgdmp という名前で作成される。

- Postgres 自動バックアップスクリプトの使い方

TARGET_DB に取得したいデータベース名スペースで区切って記述する。
ログの出力先や pg_dump コマンドのパスを各自の環境に合わせて修正する。

- スクリプト

#/bin/sh

# PostgreSQL database backup script
# Version 1.0
# Sep. 10, 2002
# Saito Hiroaki

# Dump to DATABASE_NAME_YYMMDD.pgdmp.
# Output log.

# Setting
TARGET_DB='account audit' # List target database name.

DIR=/home/postgres
LOG=$DIR/pgdump.log
BACKUPDIR=$DIR/dbbackup

# Main routine
echo "pg_dump start." `date` >>$LOG
date=`date +%Y%m%d`

for db_name in $TARGET_DB
do
  DUMP_FILE_PATH=$BACKUPDIR/${db_name}_${date}.pgdmp
  /usr/local/pgsql/bin/pg_dump $db_name -b -o -Fc > $DUMP_FILE_PATH 2>>$LOG
  echo "Database $db_name backup complete." `date` >>$LOG
done

echo "pg_dump complete." `date` >>$LOG

- ユーザ postgres のホームディレクトリ

私の環境では、ユーザ postgres のホームディレクトリは、/home/postgres ではなくて/var/lib/pgsql だ。pgd.sh は /home/postgres/pgd.sh に置いたけど。

- 上記スクリプトを、夜間バッチとして cron で毎日実行することにした。

0 6 * * * nice -19 /home/postgres/pgd.sh

2002-09-10 (Tue)

* Postgresをpg_dumpでバックアップ pg_restoreで再構築

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [Postgres] [バックアップ]

PostgresSQL のバックアップとリストア方法

- pg_dump でバックアップ

pg_dump コマンドで、ラージオブジェクトを含めてデータベースをバックアップできる。
$ pg_dump account -b -o -Fc > account_all_dump_data_20020806.pgdmp
$ pg_dump audit -b -o -Fc > audit_all_dump_data_20020806.pgdmp

- pg_dump コマンドのオプションの意味

-b ラージオブジェクトをバックアップする
-o オブジェクトIDもバックアップする
-Fc ダンプフォーマットを指定する。c はカスタムフォーマット。圧縮も行われる。

- pg_restore でリストア

再構築 (リストア) には pg_resotre コマンドを使う。-d でリストア先のデータベース名を指定する。

$ pg_restore -d account ./account_all_dump_data_20020806
$ pg_restore -d audit ./audit_all_dump_data_20020806.pgdmp

- 関連記事

2003-04-17 Postgres バックアップスクリプト version 1.1
2002-09-11 Postgres バックアップスクリプト

すべての記事の見出し (全1029件)
全カテゴリの一覧と記事の数
カテゴリごとに記事をまとめ読みできます。記事の表題だけを見たい場合は、すべての記事の見出し (カテゴリ別表示) へ。

直近30日分の記事
2007-04-23 (Mon)
2007-03-07 (Wed)
2007-02-27 (Tue)
2007-01-17 (Wed)
2007-01-15 (Mon)
2007-01-14 (Sun)
2007-01-08 (Mon)
2006-12-01 (Fri)
2006-11-22 (Wed)
2006-11-20 (Mon)
2006-11-19 (Sun)
2006-09-30 (Sat)
2006-08-29 (Tue)
2006-08-04 (Fri)
2006-07-27 (Thu)
2006-07-23 (Sun)
2006-07-17 (Mon)
2006-07-10 (Mon)
2006-07-06 (Thu)
2006-07-03 (Mon)
2006-06-29 (Thu)
2006-06-28 (Wed)
2006-06-27 (Tue)
2006-06-25 (Sun)
2006-06-19 (Mon)
2006-06-18 (Sun)
2006-06-15 (Thu)
2006-06-11 (Sun)
2006-06-01 (Thu)
2006-05-30 (Tue)
プロファイル
斎藤 宏明。エンジニアです。宇都宮市に住んでいます。
リンク
RSS
スポンサードリンク
Powered by
さくらインターネット

© 斎藤 宏明 Saito Hiroaki Gmail Address
Landscape - エンジニアのメモ http://sonic64.com/
Landscape はランドスケープと読みます。
ひらがなだと らんどすけーぷ です。