Bagaimana cara mengatasi "izin ditolak" saat menggunakan sudo dengan pengalihan di Bash?

138

Saat menggunakan sudo untuk memungkinkan pengeditan ke file, saya secara teratur mendapatkan 'izin ditolak'.

Misalnya, mouse saya gelisah dan lamban, jadi saya ingin menonaktifkan polling:

sudo echo "options drm_kms_helper poll=N">/etc/modprobe.d/local.conf

Saya diminta kata sandi, dan kemudian mendapatkan:

bash: /etc/modprobe.d/local.conf: Permission denied

Jadi saya mencoba melakukan perubahan sementara untuk menonaktifkan polling dengan menggunakan:

sudo echo N> /sys/module/drm_kms_helper/parameters/poll

Sekali lagi sistem merespons dengan:

bash: /sys/module/drm_kms_helper/parameters/poll: Permission denied

Ada ide?

Mendongkrak
sumber

Jawaban:

158

Pengalihan output (melalui >operator) dilakukan oleh shell, bukan oleh gema . Anda harus masuk sebagai root

sudo -i

Kemudian Anda dapat menggunakan pengalihan

echo N> /sys/module/drm_kms_helper/parameters/poll

Kalau tidak, Anda dapat menjalankan bash string dengan sudo

sudo bash -c "echo N> /sys/module/drm_kms_helper/parameters/poll"
shantanu
sumber
1
Anda tidak dapat menjalankan gema dengan sudo? bagaimana dengan hasil yang saya dapatkan:saji@laptop:~$ sudo echo "Hi" [sudo] password for saji: Hi
saji89
Anda dapat menulis di file, gema "sesuatu"> di suatu tempat. Itu menggunakan pipa .. Itulah masalahnya.
shantanu
4
Oke, jika itu masalahnya, harap perbarui jawaban Anda untuk mencerminkan bahwa menjalankan gema hanya masalah dalam kasus itu.
saji89
Anda tidak bisa hanya menjalankan shell builtin echosebagai sudo, kecuali jika Anda melakukan sesuatu seperti sudo bash -c 'echo …'; Namun, sistem POSIX biasanya menyediakan echoperintah eksternal seperti /bin/echopada OS X, yang dapat dijalankan sudo tanpa kesulitan. Dengan demikian, echoperintah yang biasanya Anda jalankan dan echoperintah yang Anda jalankan dengan sudo mungkin adalah dua perintah yang berbeda, tetapi serupa.
kojiro
Jika itu masalahnya, mengapa jawaban untuk pertanyaan ini menganjurkan gema? askubuntu.com/questions/840431/…
Harsha
75

Pengalihan output dilakukan oleh shell dari mana perintah telah dipanggil . Jadi, memecah semuanya menjadi bit, di sini apa yang terjadi *:

  • shell invokes sudo echo "options drm_kms_helper poll=N", yang mengeksekusi sudoperintah dengan echo "options drm_kms_helper poll=N"command line

  • sudo meminta kata sandi, membuka shell superuser dan memanggil echo "options drm_kms_helper poll=N", yang menjalankan echoperintah yang melewatinya"options drm_kms_helper poll=N"

  • gema, berjalan dengan roothak istimewa, mencetak string ke output standarnya.

  • echoperintah berakhir, shell pengguna super keluar, sudoberakhir

  • shell dari mana perintah telah dipanggil mengumpulkan output dan mencoba mengarahkannya /etc/modprobe.d/local.conf, yang hanya dapat ditulisi oleh root. Itu mendapat kesalahan "izin ditolak".

Untuk cara memperbaikinya lihat jawaban @shantanu.


(*) - sementara urutan di atas membantu untuk memahami mengapa perintah gagal, pada kenyataannya hal-hal terjadi agak rusak: shell asli memperhatikan pengalihan dan mencoba membuka file untuk menulis sebelum menjalankan sudo ...perintah. Ketika membuka file gagal, shell bahkan tidak memanggil perintah yang seharusnya menulis ke file (terima kasih kepada @PanosRontogiannis untuk menunjukkan ini).

Inilah tes cepat:

$ touch ./onlyroot.txt
$ sudo chown root:root ./onlyroot.txt
$ sudo bash -c "whoami | tee who.txt" > onlyroot.txt
bash: onlyroot.txt: Permission denied

Dalam tes di atas whoami | tee who.txtakan membuat file bernama who.txtmengandung kata "root". Namun, ketika pengalihan output gagal dalam shell panggilan, file "who.txt" juga hilang karena perintah itu tidak dipanggil.

Sergey
sumber
Kemungkinan besar shell 'forks' itu sendiri dan mencoba untuk membuka /etc/modprobe.d/local.conf sebelum mencoba 'exec' sudo yang berarti bahwa 4 langkah pertama yang Anda jelaskan tidak pernah terjadi karena file tidak dapat dibuka.
Panos Rontogiannis
1
@PanosRontogiannis: terima kasih, saya telah memperbarui jawabannya
Sergey
60

Menambahkan ke jawaban Shantanu:

... Atau Anda dapat menggunakan teeperintah seperti ini:

sudo tee /sys/module/drm_kms_helper/parameters/poll <<<10

atau jika itu output perintah:

echo 10 | sudo tee /sys/module/drm_kms_helper/parameters/poll
Tanpa judul
sumber
3
+1 masuk sebagai root adalah ide buruk untuk pekerjaan manual, dan ide yang sangat buruk untuk tugas skrip.
l0b0
2
Juga, sudo tee /sys/module/drm_kms_helper/parameters/poll > /dev/nulljika Anda tidak ingin mencetak stdoutjuga.
Fabian Tamp
16

Suatu pendekatan yang belum saya lihat disebutkan di sini adalah dengan hanya menjalankan seluruh commandline di shell-nya sendiri. Halaman sudomanual itu sendiri memberikan contoh pendekatan ini:

Untuk membuat daftar penggunaan direktori di partisi / home. Perhatikan bahwa ini menjalankan perintah dalam sub-shell untuk membuat pengalihan cd dan file berfungsi.

$ sudo sh -c "cd /home ; du -s * | sort -rn > USAGE"
kojiro
sumber
Wow terima kasih. solusi sederhana
Ketangguhan
4

Pilihan lain adalah menggunakan file sementara. Ini berguna dalam skrip bash.

temp=$(mktemp)
echo "Hello, world!" > $temp
sudo cp $temp /etc/wherever
pengguna545424
sumber
3

sudo dd of=

Untuk menambahkan seperti yang Anda inginkan:

echo inbytes | sudo dd of=outfile oflag=append conv=notrunc

atau untuk membuat ulang file dari awal:

echo inbytes | sudo dd of=outfile

Keuntungan:

  • lebih bagus daripada teesejak tidak ada /dev/nullredirection
  • lebih bagus daripada shkarena tidak ada subkulit eksplisit (tapi yang tersirat untuk pengalihan)
  • ddmemiliki banyak opsi hebat, misalnya status=progressuntuk melihat kemajuan transfer

Bekerja karena sudo meneruskan stdin ke perintah.

Ciro Santilli 新疆 改造 中心 法轮功 六四 事件
sumber
1
Ini bagus. Kami memikirkan ddbagaimana kami menimpa sistem file kami yang dulu bagus, dan tidak menyadari itu untuk tugas-tugas biasa juga - dan bahwa perintah lain sebagai root juga menyebabkan kerusakan besar jika digunakan pada file / perangkat yang salah. Sepertisudo tee , sudo ddtentu saja juga akan bekerja dengan string di sini , misalnya sudo dd of=outfile <<<'hello world',. [Terima kasih telah mengedit. NB dengan sh -c 'cmd', shadalah subproses yang merupakan shell, tetapi tidak benar-benar subkulit kecuali dalam arti semua perintah eksternal dimulai sebagai satu.]
Eliah Kagan