Sed dengan pengeditan di tempat mengubah kepemilikan grup atas file

8

Saya memiliki phpskrip shell ( ) yang terhubung dengan file target dengan cara ini:

  • memeriksa apakah file dan direktori yang dapat ditulis dengan php's is_writable()(Saya tidak berpikir bahwa ini adalah masalah)
  • melakukan edit file di tempat dengan sedperintah:

grep -q "$search" "$passwd_file" && { sed -i "s|$search|$replace|" "$passwd_file"; printf "Password changed!\n"; } || printf "Password not changed!\n"

Sebagai hasilnya saya mendapatkan (semuanya benar tetapi) file yang myuser:www-dataseharusnya myuser:myuser.

Apakah ada sedperubahan kepemilikan grup file, dan bagaimana saya menghindarinya, jika mungkin?

Miloš Đakonović
sumber

Jawaban:

16

Ada sedikit masalah dengan sedmode edit inplace -i. sedmembuat file sementara di direktori yang sama yang disebut sedy08qMA, di mana y08qMAstring yang dihasilkan secara acak. File itu diisi dengan konten yang dimodifikasi dari file asli. Setelah operasi, sedhapus file asli dan ganti nama file sementara dengan nama file asli. Jadi ini bukan suntingan inplace yang sebenarnya . Ini menciptakan file baru dengan izin dari pengguna panggilan dan nomor inode baru. Perilaku itu sebagian besar tidak buruk, tetapi misalnya, tautan keras rusak.

Namun, jika Anda ingin mengedit inplace yang sebenarnya , Anda harus menggunakannya ed. Bunyinya perintah dari stdin dan mengedit file secara langsung, tanpa file sementara (itu dilakukan melalui edbuffer memori). Praktik umum adalah menggunakan printfuntuk menghasilkan daftar perintah:

printf "%s\n" '1,$s/search/replace/g' wq | ed -s file

The printfperintah menghasilkan output sebagai berikut:

1,$s/search/replace/g
wq

Kedua baris itu adalah edperintah. Yang pertama mencari string searchdan menggantinya dengan replace. Yang kedua menulis ( w) perubahan ke file dan berhenti ( q). -smenekan keluaran diagnostik.

kekacauan
sumber
8

The -iparameter sedkarya dengan membuat file temp selama operasi, kemudian menimpa file yang sebenarnya dengan temp file pada akhirnya. Itu kemungkinan besar penyebab masalah, karena ketika membuat kepemilikan temp file default kemyuser:myuser

Anda dapat mengatur setgidbit pada direktori induk (hanya jika direktori induk dimiliki oleh grup www-data), sehingga file yang dibuat di bawah direktori ini mewarisi grup yang sama.
untuk melakukannya:

chmod g+s parent-dir-of-your-file  

Saya pikir ini adalah penggunaan setgidbit yang sangat khas .

Dave
sumber
@cuonglm Saya baru saja melakukan strace sed -i, menemukan baris berikut dalam penelusuran, apakah itu berarti ia membuat file temp di dir saat ini? open("./sedKyG9Ei", O_RDWR|O_CREAT|O_EXCL, 0600) = 4
Dave.d
@ Davidvidai: Ya, salah memori saya.
cuonglm
2

Penggunaan edbukannya sedagak berlebihan untuk ini, mengingat Anda harus memasukkan input tambahan. Distro yang sedang saya kerjakan sekarang (CentOS 5.10) memiliki -copsi untuk seditu yang menggunakan 'penyalinan' file temp daripada hanya mengganti nama file itu ketika digunakan dengan -iopsi. Saya telah mengujinya dan berfungsi dengan baik, menjaga pemilik dan grup asli saat melakukan pengeditan sisip. Ini TIDAK menghemat waktu modifikasi.

misalnya, sed -ci -e '3,5d' file.txt

  • -c menggunakan salinan alih-alih mengganti nama (yaitu, mempertahankan kepemilikan / grup)
  • -i pengeditan sebaris
  • -e skrip / ekspresi yang akan dieksekusi

Tidak yakin seberapa luas pilihan ini untuk sedseluruh distro lain. Solaris 10 tidak memilikinya, tetapi Solaris tidak memiliki banyak hal yang saya inginkan.

devnulldad
sumber
Kedengarannya sangat berguna. Namun tidak di Ubuntu 14.04, FWIW. :-(
John Rix