sudo echo "something" >> / etc / privilegedFile tidak berfungsi

586

Ini adalah pertanyaan yang cukup sederhana, setidaknya seperti seharusnya, tentang izin sudo di Linux.

Ada banyak waktu ketika saya hanya ingin menambahkan sesuatu ke /etc/hostsatau file yang serupa tetapi akhirnya tidak bisa karena keduanya >dan >>tidak diperbolehkan, bahkan dengan root.

Apakah ada cara untuk membuat pekerjaan ini tanpa harus suatau sudo sumenjadi root?

David
sumber

Jawaban:

855

Gunakan tee --appendatau tee -a.

echo 'deb blah ... blah' | sudo tee -a /etc/apt/sources.list

Pastikan untuk menghindari kutipan di dalam tanda kutip.

Untuk menghindari pencetakan data kembali ke konsol, arahkan ulang output ke / dev / null.

echo 'deb blah ... blah' | sudo tee -a /etc/apt/sources.list > /dev/null

Ingat tentang bendera ( -a/ --append)! Hanya teeberfungsi seperti >dan akan menimpa file Anda. tee -aberfungsi seperti >>dan akan menulis di akhir file.

Yoo
sumber
3
Saya benar-benar lebih suka yang ini. Ini hanya yang paling sederhana (dan itu membuat saya berpikir tentang tee, yang berguna dalam skenario lain juga).
Joachim Sauer
5
Saya setuju. Tampak lebih rapi daripada memulai sh baru juga, terutama dengan berpotensi melakukan hal-hal dengan lingkungan dll.
Sam Brightman
39
Satu hal penting yang perlu diperhatikan: JANGAN PERNAH lupakan -a! Bayangkan saja apa yang echo 'tmpfs /tmp tmpfs defaults 0 0' | sudo tee /etc/fstabakan dilakukan
mic_e
21
Di bawah OS X, ini seharusnya tee -abukan tee --append.
knite
26
Bagi mereka yang tidak mengerti apa yang dikatakan @mic_e: tanpa-a--append flag ( ) perintah akan menimpa seluruh file dengan string yang diberikan alih-alih menambahkannya sampai akhir.
totymedli
314

Masalahnya adalah shell tidak melakukan redirection, bukan sudo atau echo, jadi ini dilakukan sebagai pengguna reguler Anda.

Coba cuplikan kode berikut:

sudo sh -c "echo 'something' >> /etc/privilegedfile"
Matt P
sumber
Apa itu "batas izin sudo"? Hanya shell yang mem-parsing operator pengalihan dengan prioritas lebih tinggi daripada perintah untuk alasan yang jelas
Vinko Vrsalovic
1
Bergantung pada Anda sh, gema dapat menafsirkan urutan pelarian seperti \tdi dalam tanda kutip tunggal. Anda bisa menggunakannya printf %s 'something'sebagai gantinya.
Lri
Menggunakan tee lebih populer dan lebih kompatibel dengan distro yang lebih baru.
Eduardo B.
1
Ini adalah satu-satunya yang berfungsi apa adanya sebagai perintah SSH yang dapat dieksekusi pada node jarak jauh.
Duncan Lock
Saya setuju dengan posting lain di sini. Ini menggunakan shell dan hanya shell sehingga program lain seperti tee tidak diperlukan di sini. Ya saya tahu tee sudah diinstal, tapi mungkin tidak tergantung pada apa distro mikro yang Anda gunakan seperti alpine tulang telanjang. Saya suka bahwa Anda memiliki opsi shell juga: sudo /bin/bash -c "echo 'fs.inotify.max_user_watches = 524288' > /etc/sysctl.d/60-golang-inotify.conf"misalnya.
Ligemer
35

Masalahnya adalah bahwa shell Anda yang menangani pengalihan; itu mencoba untuk membuka file dengan izin Anda bukan dari proses yang Anda jalankan di bawah sudo.

Gunakan sesuatu seperti ini, mungkin:

sudo sh -c "echo 'something' >> /etc/privilegedFile"
Kejadian
sumber
@GordonSun ini karena sudo(karena alasan keamanan) tidak menyebarkan lingkungan ke subproses. Anda dapat menggunakan sudo -Euntuk melewati batasan ini.
arielf
1
@ GordonSun ya itu akan, saya tidak mengerti mengapa Anda terus mengulangi pernyataan ini! Jika Anda melakukannya sudo sh -c "echo 'something' >> $FILENAME", dengan tanda kutip ganda, ini akan berhasil - substitusi variabel dilakukan oleh kulit terluar, bukan kulit sudoed.
Nadav Har'El
19
sudo sh -c "echo 127.0.0.1 localhost >> /etc/hosts"
Vinko Vrsalovic
sumber
13

Perbuatan

sudo sh -c "echo >> somefile"

harus bekerja. Masalahnya adalah bahwa> dan >> ditangani oleh shell Anda, bukan oleh perintah "sudoed", jadi izinnya adalah izin Anda, bukan yang Anda gunakan untuk "sudoing".

agnul
sumber
9

Saya ingin mencatat, bagi yang penasaran, bahwa Anda juga dapat mengutip heredoc (untuk balok besar):

sudo bash -c "cat <<EOIPFW >> /etc/ipfw.conf
<?xml version=\"1.0\" encoding=\"UTF-8\"?>

<plist version=\"1.0\">
  <dict>
    <key>Label</key>
    <string>com.company.ipfw</string>
    <key>Program</key>
    <string>/sbin/ipfw</string>
    <key>ProgramArguments</key>
    <array>
      <string>/sbin/ipfw</string>
      <string>-q</string>
      <string>/etc/ipfw.conf</string>
    </array>
    <key>RunAtLoad</key>
    <true></true>
  </dict>
</plist>
EOIPFW"
msanford
sumber
1
Ini bekerja dengan baik, kecuali kutipan yang disematkan mungkin perlu diloloskan dengan \
N Jones
@NJones benar sekali! Saya akan mengedit jawaban saya. (Namun, perhatikan bahwa tidak melakukan hal ini menghilangkan internal "tetapi tidak menyebabkan perintah gagal.)
msanford
8

Dalam bash Anda dapat menggunakan teekombinasi dengan > /dev/nulluntuk menjaga stdout tetap bersih.

 echo "# comment" |  sudo tee -a /etc/hosts > /dev/null
Vytenis Bivainis
sumber
4

Menggunakan jawaban Yoo , letakkan ini di ~/.bashrc:

sudoe() {
    [[ "$#" -ne 2 ]] && echo "Usage: sudoe <text> <file>" && return 1
    echo "$1" | sudo tee --append "$2" > /dev/null
}

Sekarang kamu bisa lari sudoe 'deb blah # blah' /etc/apt/sources.list


Edit:

Versi yang lebih lengkap yang memungkinkan Anda untuk memasukkan atau mengalihkan input dari file dan menyertakan -asakelar untuk mematikan penambahan (yang diaktifkan secara default):

sudoe() {
  if ([[ "$1" == "-a" ]] || [[ "$1" == "--no-append" ]]); then
    shift &>/dev/null || local failed=1
  else
    local append="--append"
  fi

  while [[ $failed -ne 1 ]]; do
    if [[ -t 0 ]]; then
      text="$1"; shift &>/dev/null || break
    else
      text="$(cat <&0)"
    fi

    [[ -z "$1" ]] && break
    echo "$text" | sudo tee $append "$1" >/dev/null; return $?
  done

  echo "Usage: $0 [-a|--no-append] [text] <file>"; return 1
}
hololeap
sumber
2

Anda juga dapat menggunakan spongedari moreutilspaket dan tidak perlu mengarahkan ulang output (yaitu, tidak ada teesuara untuk disembunyikan):

echo 'Add this line' | sudo sponge -a privfile
Michael Goldshteyn
sumber
0

Dengan menggunakan sed -i dengan $ a , Anda dapat menambahkan teks, yang berisi variabel dan karakter khusus, setelah baris terakhir.

Misalnya, menambahkan $ NEW_HOST dengan $ NEW_IP ke / etc / hosts:

sudo sed -i "\$ a $NEW_IP\t\t$NEW_HOST.domain.local\t$NEW_HOST" /etc/hosts

Opsi sed menjelaskan:

  • -Saya di tempat
  • $ untuk baris terakhir
  • a untuk ditambahkan
Noam Manos
sumber
0

gema 'Hello World' | (sudo tee -a /etc/apt/sources.list)

Sudev Shetty
sumber
0

Bagaimana dengan:
echo text | sudo dd status = none of = privilegedfile
Saya ingin mengubah / proc / sys / net / ipv4 / tcp_rmem.
Saya lakukan:
sudo dd status = tidak ada = / proc / sys / net / ipv4 / tcp_rmem <<< "4096 131072 1024000"
menghilangkan gema dengan dokumen baris tunggal

Marcelo Pacheco
sumber
1
Silakan luangkan waktu sejenak untuk membaca bantuan pengeditan di pusat bantuan . Memformat pada Stack Overflow berbeda dari situs lain.
Dharman
-1

Ini bekerja untuk saya: perintah asli

echo "export CATALINA_HOME="/opt/tomcat9"" >> /etc/environment

Perintah kerja

echo "export CATALINA_HOME="/opt/tomcat9"" |sudo tee /etc/environment
Fthi.a.Abadi
sumber
1
Seharusnya tee -a. Hanya teeakan menimpa file!
codeforester
-6

Bisakah Anda mengubah kepemilikan file kemudian mengubahnya kembali setelah digunakan cat >>untuk menambahkan?

sudo chown youruser /etc/hosts  
sudo cat /downloaded/hostsadditions >> /etc/hosts  
sudo chown root /etc/hosts  

Sesuatu seperti ini cocok untukmu?

pixistix
sumber
4
Chown adalah perintah destruktif untuk digunakan. Jika seorang manajer config menggunakannya untuk memperbarui / etc / hosts, tiba-tiba / etc / hosts milik pengguna config dan bukan root. yang berpotensi menyebabkan proses lain tidak memiliki akses ke / etc / hosts. Inti dari sudo adalah untuk menghindari sesuatu masuk ke root dan melalui sudoer, lebih banyak batasan dapat ditumpuk juga.
David