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?

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.


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"

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"

@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


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".


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"

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

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
}

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

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


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


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

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?


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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.