2020-09-01_ディレクトリを権限とオーナー情報を指定して一括作成したい

  • 検索タグ用: install mkdir ディレクトリ構成のみ 移行

このページで分かること

ディレクトリ構成のみの移行方法(権限・オーナー情報を含めてのコピー)

よくある現行環境のディレクトリ構成そのままで新環境に構築したいときのTIPSを記載します。ディレクトリの中身まで移行対象であればtarで固めたりしますがディレクトリの構成だけを移行したい場合の方法です。

※権限・オーナー情報は同一にして空ディレクトリを一括作成します。

環境

  • OS: fedora31(WSL環境上に構築)

流れだけコマンドでさっくり読みたい

ザックリとまとめ。詳細解説は別項。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
## #作成するリストファイルのベース名
## #移行対象のルートディレクトリ
#r list_name='/tmp/dir-list'
#r target_dir='/etc/'

## #移行元ディレクトリリスト作成
#r find ${target_dir} -type d | xargs -I{} stat --format='%a %U %G %n' {} | tee -a ${list_name}-origin

## #同マシンの別ディレクトリに移行するために加工
#r cat ${list_name}-origin | sed -e "s@ ${target_dir}@ /tmp/testdir${target_dir}@" | tee ${list_name}-create

## #加工後のリストをgawkでコマンド化(コマンド内容確認確認)
#r cat ${list_name}-create | gawk '{print "install -v -m "$1" -o "$2" -g "$3" -d "$4}' | tee ${list_name}-create-command

## #作成したコマンドを実行
#r cat ${list_name}-create-command | bash -ex

## #作成したディレクトリと元ディレクトリを比較用リストを作成
#r cat ${list_name}-create | gawk '{print $4}' | xargs -I{} stat --format='%a %U %G %n' {} | sed -e 's@ /tmp/testdir/etc/@ /etc/@' | tee ${list_name}-create-after

## #作成したディレクトリと元ディレクトリを比較(差異なしでOK)
#r diff -u0 ${list_name}-origin ${list_name}-create-after

詳細について

対象ディレクトリの確認

前提として同じマシンの別ディレクトリに移行することにします。例えば/etc配下のディレクトリ構成を再現したい場合は、対象のディレクトリリストを作成します。今回はetc配下のfind結果上位25ディレクトリを対象にしたいと思います。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#r find /etc/ -type d | head -25
/etc/
/etc/pkgconfig
/etc/pkgconfig/personality.d
/etc/systemd
/etc/systemd/system
/etc/systemd/system/getty.target.wants
/etc/systemd/system/sysinit.target.wants
/etc/systemd/system/multi-user.target.wants
/etc/systemd/system/network-online.target.wants
/etc/systemd/system/timers.target.wants
/etc/systemd/system/sockets.target.wants
/etc/systemd/user
/etc/systemd/user/sockets.target.wants
/etc/systemd/network
/etc/yum.repos.d
/etc/gnupg
/etc/openldap
/etc/openldap/certs
/etc/dbus-1
#

statコマンドについて

次に対象ディレクトリの権限、オーナー情報を取得します。ポイントとしてはls -lコマンドではなくstatコマンドを使用して権限を数値で取得します。後工程のディレクトリ作成で使用するinstallコマンドの権限指定が数値であるためです。更にコマンド生成に使用するgawkのデフォルト区切り文字である半角スペースでstatコマンドのフォーマットを指定します。 ※chomdmkdir -mも数値しているのでinstallコマンドを使用しなくても 数値取得のほうが勝手が良いです。

1
2
## #凡例
#r stat --format='%a %U %G %n' ${target_dir} or ${target_file}

対象ディレクトリリストの作成(権限・オーナ・ディレクトリ名)

先程のfindと合わせて以下のように実施しリストファイルを作成します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
## #find結果をxargsでstatに渡してリダイレクトでファイル保存
#r find /etc/ -type d | head -25 | xargs -I{} stat --format='%a %U %G %n' {} | tee /tmp/dir-list
755 root root /etc/
755 root root /etc/pkgconfig
755 root root /etc/pkgconfig/personality.d
755 root root /etc/systemd
755 root root /etc/systemd/system
755 root root /etc/systemd/system/getty.target.wants
755 root root /etc/systemd/system/sysinit.target.wants
755 root root /etc/systemd/system/multi-user.target.wants
755 root root /etc/systemd/system/network-online.target.wants
755 root root /etc/systemd/system/timers.target.wants
755 root root /etc/systemd/system/sockets.target.wants
755 root root /etc/systemd/user
755 root root /etc/systemd/user/sockets.target.wants
755 root root /etc/systemd/network
755 root root /etc/yum.repos.d
755 root root /etc/gnupg
755 root root /etc/openldap
755 root root /etc/openldap/certs
755 root root /etc/dbus-1
755 root root /etc/dbus-1/system.d
755 root root /etc/dbus-1/session.d
755 root root /etc/sasl2
755 root root /etc/statetab.d
755 root root /etc/rc.d
755 root root /etc/rc.d/rc5.d
#

別環境で同一ディレクトリ構成ならこのリストを使用しコマンドを生成すればOKです。

同一環境用にディレクトリ名の加工

今回は同じマシンの/tmp/testdir/配下に/etcディレクトリを再現しますのでベースリストに/tmp/testdir/etc/の様な形式に修正します。sedを使用してやってみましょう。

1
2
3
4
5
## #上位3件だけサンプルで表示
#r cat /tmp/dir-list | sed -e 's@ /etc/@ /tmp/testdir/etc/@' | tee /tmp/dir-list-creat
755 root root /tmp/testdir/etc/
755 root root /tmp/testdir/etc/pkgconfig
755 root root /tmp/testdir/etc/pkgconfig/personality.d

sedの置換対象の前に半角スペースを入れているのはroot /etc/の部分にヒットさせるためです。/etc/だけではディレクトリ階層の途中に同じキーワードが存在した場合にヒットしてしまいます。

ディレクトリ作成コマンドリストの作成と実行

次にディレクトリ作成用のコマンドリストをgawkで生成します。今回はmkdirではなく installコマンド で権限・オーナー情報を一括設定してディレクトリを作成します。 以下のコマンドでディレクトリ作成コマンドリストを生成し、bashにリダイレクトすることでコマンドを実行します。bash -eでエラー時に停止します。bashの実行を負いたい場合は-xオプションを追加しましょう。

1
2
3
4
5
6
7
8
## #teeでコマンドを確認しながらリダイレクト
#r cat /tmp/dir-list-creat | gawk '{print "install -v -m "$1" -o "$2" -g "$3" -d "$4}' | tee /tmp/dir-list-creat-command
## #実行
#r cat /tmp/dir-list-creat-command | bash -e
install: creating directory '/tmp/testdir'
install: creating directory '/tmp/testdir/etc/'
install: creating directory '/tmp/testdir/etc/pkgconfig'
...続く...

元ディレクトリの比較用リストの作成と比較

無事に作成できましたので権限・オーナー情報が元ディレクトリと合致するかを突き合わせます。比較元は/tmp/dir-list(元ディレクトリリスト)と作成したディレクトリリストになります。/tmp/dir-list-createを加工しても良いですが念のためにstatで情報取得し直して付け加えていた/tmp/testdir/を削り今回作成したディレクトリの権限・オーナが合致するかを確認します。 ※dir-list-createで十分かもしれませんが最新の情報で取得し直したほうが、より正確と思ったので態々取得し直しています。

1
2
3
4
## #diff比較用リスト作成
#r cat /tmp/dir-list-creat | gawk '{print $4}' | xargs -I{} stat --format='%a %U %G %n' {} | sed -e 's@ /tmp/testdir/etc/@ /etc/@' | tee /tmp/dir-list-creat-after
## #比較実施(差異なしでOK)
#r diff -u0 /tmp/dir-list-orgin /tmp/dir-list-creat-after

手順は以上になります。

余談

tarballで展開してファイルだけ消せばと思ったりもしますが、意図せぬ巻き込みも怖いので作成する方式を取りました。作成より消込のほうが早かったりした場合は一考するのもアリかと思います。

久々にOSレイヤーの構築作業やっていて半自動化手順にしたいなぁと思いまとめてみました。多分使いどころは多いはず……たぶん……きっと。