Bagaimana saya bisa mendapatkan perintah sudo untuk menggunakan pengaturan di /root/.bashrc

9

Saya telah menyesuaikan .bashrcdengan sejumlah alias, khusus lldanexport LS_OPTIONS='--color=auto'

Sayangnya ini tidak berfungsi ketika digunakan dengan sudo, jadi saya juga dimodifikasi /root/.bashrc, tetapi ini tampaknya tidak membuat perbedaan.

sudo envmenunjukkan HOME=/rootdanSHELL=/bin/bash

Bagaimana saya bisa mendapatkan sudoperintah untuk menggunakan pengaturan /root/.bashrc?

Saya mengerti bahwa ini hanya terjadi ketika bashdijalankan secara interaktif, jadi saya terbuka untuk saran lain tentang cara menyesuaikan.

Milliways
sumber
@ daniel-gelling - Saya selalu merasa Q ini masalah XY - meta.stackexchange.com/questions/66377/what-is-the-xy-problem . Judul menyiratkan bahwa mereka menginginkan sesuatu dari /root/.bashrctetapi yang benar-benar dicari Q adalah alias dari file ini - ini tidak mungkin untuk ini - unix.stackexchange.com/questions/1496/… .
slm
@slm Yang saya setelah ini menambahkan metode untuk bashrc - seperti yang telah saya lakukan dalam file .bashrc pribadi saya serta file .bashrc untuk root untuk "menonaktifkan" yang -rpilihan untuk crontab: crontab () { [[ $@ =~ -[iel]*r ]] && echo '"r" not allowed' || command crontab "$@" ;}. Ini berfungsi ketika masuk sebagai salah satu pengguna, namun ketika saya menjalankannya sudo crontab -rmasih dijalankan.
Daniel Gelling
@DanielGelling - lihat apakah jawaban saya cocok untuk skenario Anda.
slm

Jawaban:

6

sudomenjalankan executable, bukan perintah shell. Jadi tidak tahu tentang alias. Jika Anda menjalankan sudo ls, itu seperti sudo /bin/ls, itu tidak menggunakan lsalias apa pun yang mungkin Anda miliki.

Anda dapat menyebabkan sudo lsuntuk memperluas alias dengan memasukkan yang berikut ini di .bashrc:

alias sudo='sudo '

Perhatikan spasi tambahan - yang memberi tahu shell untuk melanjutkan alias ekspansi dengan kata yang muncul setelahnya sudo. Berhati-hatilah bahwa memperluas alias setelah sudo mungkin tidak selalu merupakan ide yang baik, tergantung pada jenis alias apa yang Anda miliki.

Lebih jauh lagi, sudo menghapus sebagian besar variabel dari lingkungan. Ini tidak akan memengaruhi alias seperti alias ls='ls $LS_OPTIONS', karena itu adalah variabel shell yang digunakan oleh shell saat sedang memperluas perintah (dan mengekspornya dari .bashrctidak berguna). Tetapi itu akan mempengaruhi variabel yang digunakan oleh perintah, seperti LS_COLORS. Anda dapat mengonfigurasi sudo untuk menjaga variabel lingkungan tertentu dengan mengedit konfigurasinya: jalankan visudodan tambahkan baris

Defaults env_keep += "LS_COLORS"

Dengan pengaturan ini, sudo llakan memberikan warna yang biasa Anda gunakan.

Atau, Anda dapat menjalankan shell root dengan sudo -s. Shell ini akan memuat file konfigurasinya ( ~/.bashrcuntuk bash). Bergantung pada bagaimana sudo dikonfigurasi, ini dapat tetap HOMEdiatur ke direktori home Anda, atau mengubahnya menjadi /root. Anda bisa memaksa direktori home diatur ke root dengan sudo -Hs; sebaliknya, untuk menjaga direktori home asli, jalankan sudo env HOME="$HOME" bash.

Gilles 'SANGAT berhenti menjadi jahat'
sumber
3

Terima kasih kepada mereka yang menjawab, yang mendorong saya untuk membaca man sudolebih cermat.

sudo -s Jika tidak ada perintah yang ditentukan, shell interaktif dijalankan.

Shell interaktif ini menggunakan /root/.bashrcdan dengan demikian termasuk penyesuaian saya.

Itu memang mengharuskan perintah dimasukkan secara terpisah, tetapi ini OK.

Milliways
sumber
2

Latar Belakang

Saya selalu merasa pertanyaan ini adalah masalah XY . Judul menyiratkan bahwa mereka menginginkan sesuatu /root/.bashrctetapi sebenarnya pertanyaannya adalah alias dari file ini - ini secara luas diyakini tidak mungkin dilakukan per ini - Mengapa skrip Bash saya tidak mengenali alias? .

Ini pada dasarnya dengan desain bahwa alias Anda tidak akan dijemput di sudodan di tempat lain karena mereka tidak portabel, dan ini adalah pendapat saya tentang mereka juga.

Apa pun yang ada di lingkungan pengguna tidak boleh diasumsikan oleh skrip dan perangkat lunak apa pun yang dapat berjalan pada kotak yang diberikan. Tapi saya menyadari bahwa ada skenario di mana mungkin ada beberapa alias dalam akun pengguna tertentu $HOME/.bashrcyang mungkin ingin dimanfaatkan orang lain dalam skenario interaktif.

Untuk itu Anda bisa memberi tahu penerjemah Bash untuk memperluas alias apa pun yang ditemukannya selama proses login di luar perilaku shell normal yang Anda alami ketika menggunakan sudo.

Contoh

Mendirikan

Untuk mengaturnya, saya telah menambahkan alias, variabel lingkungan, dan fungsi berikut ke pengguna /root/.bashrcdan /root/.bash_profilefile root saya .

$ grep smurf ~/.bashrc
alias brc_smurf='echo "ran alias from /root/.bashrc"'
export brc_smurf_env='var from /root/.bashrc'
bpf_smurf_func() { echo 'ran func from /root/.bash_profile'; }

$ grep smurf ~/.bash_profile
alias bpf_smurf='echo "ran alias from /root/.bash_profile"'
export bpf_smurf_env='var from /root/.bash_profile'
brc_smurf_func() { echo 'ran func from /root/.bashrc'; }

Tanpa melakukan apa pun, kedua pekerjaan ini (tidak ada kejutan):

$ sudo brc_smurf
sudo: brc_smurf: command not found

$ sudo bpf_smurf
sudo: bpf_smurf: command not found

Kita melihat bahwa aliasperintah tidak menunjukkan alias ketika dijalankan di sudo:

$ sudo alias
$

Perilaku ini adalah petunjuk Anda bahwa Anda seharusnya tidak berharap alias dapat diakses. Tapi kami melanjutkan ...

Langkah # 1 - alias terlihat

Jika kami menjalankan, bash -cikami dapat mendorong Bash untuk setidaknya membaca $HOME/.bashrc:

$ sudo bash -ci 'alias' | grep smurf
alias brc_smurf='echo "ran alias from /root/.bashrc"'

Keren, jadi mungkin kita bisa menjalankannya?

$ sudo bash -ci 'alias; brc_smurf'
bash: alias; brc_smurf: No such file or directory

Langkah 2 - shopt -s expand_aliases

Nggak. Sekali lagi ini adalah dengan desain, kami melakukan sesuatu yang seharusnya tidak kami lakukan, jadi ada sejumlah "pengaman" yang harus kami nonaktifkan. "keamanan" lainnya adalah Bash.

$ sudo bash -ci 'shopt -s expand_aliases; alias; brc_smurf'
alias brc_smurf='echo "ran alias from /root/.bashrc"'
alias cp='cp -i'
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias grep='grep --color=auto'
alias l.='ls -d .* --color=auto'
alias ll='ls -l --color=auto'
alias ls='ls --color=auto'
alias mv='mv -i'
alias rm='rm -i'
alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'
ran alias from /root/.bashrc

Di sini kita dapat melihat pesan kami dari /root/.bashrc, kami telah berhasil menjalankan alias pengguna root brc_smurf.

Langkah # 3 - bagaimana dengan env vars?

Jika Anda menggunakan metode yang ditunjukkan di atas ini sekarang harus bekerja juga.

$ sudo bash -ci 'shopt -s expand_aliases; brc_smurf; echo $brc_smurf_env'
ran alias from /root/.bashrc
var from /root/.bashrc

Langkah # 4 - bagaimana dengan fungsi?

Ini juga berfungsi seperti yang diharapkan:

$ sudo bash -ci 'shopt -s expand_aliases; brc_smurf; echo $brc_smurf_env;brc_smurf_func'
ran alias from /root/.bashrc
var from /root/.bashrc
ran func from /root/.bashrc

TLDR;

Anda dapat melakukan ini untuk mendapatkan akses ke variabel lingkungan + alias dari /root/.bashrc:

$ sudo bash -ci 'shopt -s expand_aliases; <cmds>'

Awasi

Metode ini memungkinkan konten /root/.bashrc, tidak mengambil konten /root/.bash_profile.

Referensi

slm
sumber
Yap, meskipun ada beberapa perbedaan kecil di antara mereka, mari kita tidak masuk ke detail di sini ;-). Bagaimanapun, bisakah Anda membantu saya dengan situasi yang saya nyatakan di komentar pertanyaan: menggunakan fungsi .bashrcdengan sudo; khusus menghapus -ropsi dari crontab?
Daniel Gelling
Oke, tapi ini berarti aku harus lari: sudo bash -ci 'alias; shopt -s expand_aliases; echo $brc_smurf_env'bukannya yang sederhana sudo echo $brc_smurf_env?
Daniel Gelling
Anda dapat menghapus alias, itu hanya untuk menunjukkan kepada mereka, yang perlu Anda lakukansudo bash -ci 'shopt -s expand_aliases; <cmds>'
slm
Itu akan banyak mengetik hanya untuk mengedit crontab saya untuk root. Biarkan saya membuat alias untuk itu :-P
Daniel Gelling
@DanielGelling - ya, selamat datang di semua kesenangan di dalam shell shell.
slm
0

Ada banyak pengaturan di file / etc / sudoers khusus atau pengaturan lingkungan ketika perintah sudo dijalankan (mis. Memastikan PATH hanya memiliki lokasi tepercaya) tetapi tergantung pada apa yang Anda harapkan untuk keluar dari ini Anda mungkin tidak dapat melakukan apa yang Anda inginkan jika itu melibatkan menjalankan perintah aktual dalam shell untuk mengatur lingkungan. Sudoing secara khusus tidak memberi Anda shell login root sehingga tidak akan mengatur profil reguler untuk Anda.

hvindin
sumber
0

Katakanlah kita mengedit /root/.bashrc menjadi:

$ sudo su -
Password: ******
# cat ~/.bashrc

echo "root bashrc file was read"
PATH=~/bin:$PATH
echo "$PATH"
export USERVAR=set
echo "$USERVAR"

umask 022
alias ll='ls $LS_OPTIONS -l'
alias l='ls $LS_OPTIONS -lA'

Mari keluar dan masuk kembali untuk membuat bash membaca file:

# exit
$ sudo su -
root bashrc file was read
/root/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
set
root@here:~# alias l
alias l='ls $LS_OPTIONS -lA'
root@here:~# 

Seperti yang Anda lihat, file telah dibaca, PATH telah diubah dan alias telah ditetapkan. Semua fungsional sesuai permintaan Anda.

Namun, sudo masih tidak berfungsi seperti yang Anda harapkan.

root@here:~# exit
$ sudo env | grep USERVAR              # no output 
$ sudo env | grep PATH
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

PATH belum berubah. Mungkin ada cara untuk mengubah jalur di sudoers, tetapi saya sangat menyarankan Anda untuk menghindari melakukan itu. Lagi pula, alias, fungsi, dan beberapa perubahan lainnya masih tidak akan diterapkan dengan mengubah hanya PATH. File harus bersumber. Melakukan itu untuk setiap skrip atau perintah akan meminta komputer untuk melakukan lebih banyak pekerjaan tanpa manfaat nyata. Script tidak menggunakan alias (tidak ada penggunaan praktis untuk mereka di dalam skrip).

Jadi, cukup login, .bashrcfile akan dimuat secara otomatis dan mulai bekerja.

Anda dapat memulai bash karena ini:

$ sudo bash
root bashrc file was read
/root/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
set
root@mail:/home/isaac/me/temp/clocks-master#

Tetapi seperti yang Anda lihat di atas, pwd (direktori kerja) tidak berubah, dan, jika Anda memeriksa sedikit lebih, beberapa pengaturan lain tidak berubah juga. Itulah sebabnya perintah yang benar adalah menggunakan:

$ sudo su -

Jika perintah itu terlalu panjang untuk diketik, buat alias atau fungsi di pengguna (bukan root) tempat perintah itu akan digunakan, sesuatu seperti:

$ alias mysu='sudo su -'
$ mysu
# 
Ishak
sumber
0

TL; DR: Anda dapat menggunakan sudo -iuntuk menjalankan fungsi yang ditentukan /root/.bashrc(tetapi bukan alias) dan juga memiliki akses ke variabel yang diekspor dari file itu:

argumen perintah sudo -i 

Meskipun demikian, alias tidak berfungsi di sana, tetapi Anda dapat dengan mudah mengonversinya ke fungsi jika Anda ingin membuatnya tersedia sudo -i.

Baca terus untuk analisis penuh dan detail lebih lanjut.


Ada beberapa masalah di sini, beberapa dalam cara kerja sudo dan beberapa dalam cara bash itu bekerja ...

Secara default, sudohanya akan mencari perintah dan akan memotong shell, jadi hanya menjalankan sudo llhanya akan bekerja jika ada yang dapat lldieksekusi di salah satu direktori di $PATH. Jadi, untuk menggunakan alias (atau fungsi), Anda perlu memastikan shell dipanggil sebagai bagian dari proses.

Salah satu caranya adalah dengan menjalankan sesuatu seperti sudo shatau sudo bash, meskipun modern sudo(saya menguji ini pada sudo 1.8.19p1) memiliki opsi -sdan -iuntuk tujuan itu.

Jadi satu percobaan akan menjadi sesuatu seperti sudo -s ll(yang setara dengan sudo bash -c 'll', dengan asumsi Anda $SHELLadalah Bash, yang tampaknya menjadi kasus berdasarkan yang rcfileAnda sebutkan.) Tapi itu tidak berhasil, karena ia memulai shell dalam non-interaktif, mode non-login, yang tidak membaca file startupnya. Ini pada dasarnya sama seperti jika Anda menulis skrip shell dan menggunakannya #!/bin/bashuntuk menjalankannya. Alias ​​(dan fungsi) yang Anda miliki di Anda ~/.bashrctidak akan dapat diakses dari skrip itu ...

Jadi selanjutnya adalah -iopsi, yang menciptakan shell login. Itu lebih menjanjikan, karena akan membaca file startup Anda! Namun, sudo -i ll(setara dengan sudo bash -l -c 'll') masih tidak akan berfungsi. Jadi bagaimana mungkin, mengingat memang membaca definisi llalias?

Nah, penjelasan selanjutnya di sini adalah bahwa, secara default, bash tidak akan memperluas alias, kecuali ketika shell bersifat interaktif ... Shell ini dimulai dengan sudo -i(atau bash -l) shell login , tetapi masih belum interaktif.

Jadi langkah selanjutnya adalah mendapatkan shell interaktif , yang kemudian berfungsi :

sudo bash -i -c 'll'

(Memiliki kedua login dan interaktif juga baik, tentu saja, bash -l -i -c ...akan berfungsi.)

Alternatif lain adalah tetap menggunakan shell login (non-interaktif) tetapi memintanya secara eksplisit untuk memperluas alias, jadi ini juga akan berfungsi:

sudo bash -l -O expand_aliases -c 'll'

(Kasus di mana bash bersifat interaktif tidak memerlukan shell login , karena itu sudah cukup untuk membaca file inisialisasi, tetapi yang ini perlu -lmembacanya.)

Ini adalah baris perintah yang cukup panjang ... Dan mereka juga mengharuskan Anda mengutip seluruh perintah shell, jadi jika Anda memanggil alias dengan argumen, Anda harus mengubah semua itu menjadi string ... Jadi itu semacam kikuk untuk menggunakan ...

Perhatikan bahwa sebelumnya saya berbicara tentang alias dan fungsi ... Itu sengaja, karena fungsi sebenarnya jauh lebih nyaman di sini. Anda tidak perlu sesuatu yang istimewa (seperti memiliki shell interaktif, atau mengatur opsi tertentu) untuk menjalankan fungsi pada shell, selama Anda mencari definisi mereka.

Jadi, jika Anda mendefinisikan llsebagai fungsi alih-alih alias, Anda dapat menggunakannya secara langsung dengan -ipintasan sudo :

sudo -i ll

Dan jika Anda memiliki baris perintah yang lebih panjang, dengan argumen, Anda bisa meneruskannya langsung di sini juga:

sudo -i ll -C -R /etc

(Bandingkan dengan sudo bash -i -c 'll -C -R /etc'.)

Fungsi juga jauh lebih fleksibel dan biasanya lebih mudah dipelihara ... Biasanya mudah untuk mengubah alias menjadi fungsi, satu-satunya peringatan adalah untuk selalu menggunakan di "$@"mana Anda mengharapkan argumen tambahan akan diambil (biasanya di akhir alias.)

Misalnya, alias ini:

alias ll='ls $LS_OPTIONS -l'

Dapat diubah menjadi fungsi ini:

ll () {
    ls $LS_OPTIONS -l "$@"
}

Mereka, untuk sebagian besar tujuan, setara. Dan, seperti yang disebutkan sebelumnya, fungsi harus dapat diakses langsung dari sudo -i, jadi itu bonus tambahan.

Saya harap Anda menemukan jawaban dan penjelasan ini bermanfaat!

filbranden
sumber
DV - Saya tidak merasa ini memperbaiki situasi lagi daripada apa yang sudah ada di sini.
slm
1
@slm Saya kira jawaban saya adalah menambahkan sesuatu, karena tidak ada jawaban sebelumnya yang menyebutkan formulir sudo -i command argumentsuntuk dapat menjalankan fungsi dari /root/.bashrcdan telah mengekspor variabel yang tersedia. Tapi saya melihat bagaimana jawaban saya mungkin terlalu lama dan info itu agak terkubur di sana ... Jadi saya menambahkan TL; DR untuk meringkasnya (sambil tetap menyimpan rincian teknis penyelidikan sekitar.) Silakan lihat lagi.
filbranden