web-dev-qa-db-ja.com

sed:/ etc / fstabのエントリを置き換える

現在、システムの一部を強化しています。その強化プロセスの一環として、/ etc/fstabのいくつかのエントリを更新して、さまざまなパーティションの一部の機能を制限する必要があります。

そうは言っても、sedインライン置換を使用して行を更新できるようにしたいと思います。以下は、現在の/ etc/fstabからの抜粋です。

# /etc/fstab
# Created by anaconda on Wed Feb 21 09:37:23 2018
/dev/mapper/vg1-lv_root /                       ext4    defaults        1 1
/dev/mapper/vg1-lv_home /home                   ext4    defaults        1 2
tmpfs                   /dev/shm                tmpfs   defaults        0 0

Sedコマンドを実行した後、ファイルを次のようにします。

# /etc/fstab
# Created by anaconda on Wed Feb 21 09:37:23 2018
/dev/mapper/vg1-lv_root /                       ext4    defaults        1 1
/dev/mapper/vg1-lv_home /home                   ext4    defaults,nodev        1 2
tmpfs                   /dev/shm                tmpfs   defaults        0 0

基本的に、ルートパーティションではないext [2-4]のすべての行に「nodev」を追加する必要があります。

私がまとめたsedコマンドはこれに近づきますが、何らかの理由で正規表現を「/」パーティションに一致させないため、常にその行も更新します。

sed '/^[^#].*ext[2-4]/s/defaults/defaults,nodev/g' /etc/fstab

Vg1-lv_rootではなく、スペースで囲まれた「/」をキーオフしたいと思います。以下は機能しますが、解決策は不格好であるため、私はこのソリューションが好きではありません。

sed '/^[^#].*ext[2-4]/s/defaults/defaults,nodev/g' /etc/fstab | sed '/^[^#].*root.*ext[2-4]/s/defaults,nodev/defaults/' > /etc/fstab
4
Jason

awkを使用して文字列を追加するロジックを追加し、columnを使用して最終的な出力ファイルを再フォーマットできます。 /etc/および/tmp/フォルダーへの書き込み権限があると想定します

tempfile=$(mktemp /tmp/tmpfile.XXXXXXXX)

これにより、/tmp/パスに一時ファイルが作成され、awk出力を書き込んで元のファイルにリダイレクトできます。

awk '$3 ~ "ext[2-4]"{ $4=$4",nodev" }1 ' /etc/fstab | column -t > "$tempfile" && mv -- "$tempfile" /etc/fstab

column -tの部分は冗長であり、出力ファイルを読みやすくするために必要であり、乱雑で扱いにくいものにするために必要です。

5
Inian

次に、より簡単なsedアプローチを示します。

$ sed -E 's|(\s/\S+\s+ext[2-4]\s+defaults)|\1,nodev|' fstab 
# /etc/fstab
# Created by anaconda on Wed Feb 21 09:37:23 2018
/dev/mapper/vg1-lv_root /                       ext4    defaults        1 1
/dev/mapper/vg1-lv_home /home                   ext4    defaults,nodev        1 2
tmpfs                   /dev/shm                tmpfs   defaults        0 0

トリックは、空白とそれに続く/および1つ以上の空白以外の文字(\s/\S+)、次にext[2-4]を探しますが、先頭に空白(\s+ext[2-4])がある場合のみです、より多くの空白とdefaults。これは、関心のあるケースにのみ一致するはずです。一致する場合は、一致全体をそれ自体とnodev\1,nodevに置き換えます。

ただし、これがどれほど移植可能かはわかりません。拡張正規表現の-Eは、多くのsed実装でサポートされていますが、POSIXではサポートされていません。よりポータブルなアプローチについては、Perlで同じアイデアを試すことができます。

$ Perl -pe 's|(\s/\S+\s+ext[2-4]\s+defaults)|\1,nodev|' fstab 
# /etc/fstab
# Created by anaconda on Wed Feb 21 09:37:23 2018
/dev/mapper/vg1-lv_root /                       ext4    defaults        1 1
/dev/mapper/vg1-lv_home /home                   ext4    defaults,nodev        1 2
tmpfs                   /dev/shm                tmpfs   defaults        0 0

どちらの場合も、ファイルをその場で編集するには、-iを使用します。

Perl -i -pe 's|(\s/\S+\s+ext[2-4]\s+defaults)|\1,nodev|' fstab 
sed -E 's|(\s/\S+\s+ext[2-4]\s+defaults)|\1,nodev|' fstab 

または、BSDまたはOSXの場合sed

sed -i '' -E 's|(\s/\S+\s+ext[2-4]\s+defaults)|\1,nodev|' fstab 

上記は、defaultsオプションが唯一のオプション、または少なくとも最後のオプションのいずれかであることを前提としていることに注意してください。たとえば、nodev,defaultsのようなものがある場合は失敗します。

5
terdon

もちろん、質問を投稿してから10分後、ついに次のようにして自分のやりたいことを実行させることができました。

sed -r '/^[^#].*[ \t]+\/[^[:space:]].*ext[2-4]/s/defaults/defaults,nodev/g' /etc/fstab

誰かがより明確で、より簡単な答えを持っているなら、私はそれを聞きたいです。ありがとう!

3
Jason

一致を除外することは維持が困難です。必要なパーティションのみを一致させる方が安全です。また、一致する1行のみの場合、末尾の「g」は不要です。

sed -r 's#(/home\s.*defaults)\s#\1,nodev #' /etc/fstab 
0
hellork