Alias ​​tidak tersedia saat menggunakan sudo

161

Saya bermain-main dengan alias hari ini dan saya perhatikan bahwa alias tidak tersedia saat menggunakan sudo:

danny@kaon:~$ alias
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias grep='grep --color=auto'
alias l='ls -CF'
alias la='ls -A'
alias ll='ls -alF'
alias ls='ls --color=auto'

danny@kaon:~$ ll -d /
drwxr-xr-x 23 root root 4096 2011-01-06 20:29 //

danny@kaon:~$ sudo -i
root@kaon:~# ll -d /
drwxr-xr-x 23 root root 4096 2011-01-06 20:29 //
root@kaon:~# exit
logout

danny@kaon:~$ sudo ll -d /
sudo: ll: command not found

Apakah ada alasan mengapa Anda tidak dapat menggunakan alias saat menggunakan sudo?

kemra102
sumber
Apakah Anda mendeklarasikan alias tersebut di .bashrc pada / root /
Luciano Facchinelli
2
@LucianoFacchinelli: /root/.bashrctidak bisa dibaca saat menjalankan perintah melalui sudo.
Flimm
serverfault.com/questions/61321/how-to-pass-alias-through-sudo
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件
@ Flimm: Bagaimana sudo -i?
Evi1M4chine

Jawaban:

251

Tambahkan baris berikut ke Anda ~/.bashrc:

alias sudo='sudo '

Dari manual bash :

Alias ​​memungkinkan string untuk menggantikan kata ketika digunakan sebagai kata pertama dari perintah sederhana. Shell memelihara daftar alias yang mungkin diatur dan tidak disetel dengan perintah builtin alias dan unalias.

Kata pertama dari setiap perintah sederhana, jika tidak dikutip, diperiksa untuk melihat apakah ada alias . Jika demikian, kata itu diganti dengan teks alias. Karakter '/', '$', '`', '=' dan salah satu dari metakarakter shell atau mengutip karakter yang tercantum di atas mungkin tidak muncul dalam nama alias. Teks pengganti dapat berisi input shell yang valid, termasuk karakter meta shell. Kata pertama dari teks pengganti diuji untuk alias, tetapi kata yang identik dengan alias yang diperluas tidak diperluas untuk kedua kalinya. Ini berarti bahwa seseorang dapat alias ls ke "ls-F", misalnya, dan Bash tidak mencoba untuk memperluas teks pengganti secara rekursif. Jika karakter terakhir dari nilai alias adalah spasi atau karakter tab, maka kata perintah berikutnya setelah alias juga diperiksa untuk ekspansi alias .

(Penekanan milikku).
Bash hanya memeriksa kata pertama dari sebuah perintah untuk alias, kata-kata setelah itu tidak dicentang. Itu berarti dalam perintah seperti sudo ll, hanya kata pertama ( sudo) diperiksa oleh bash untuk alias, lldiabaikan. Kami dapat memberitahu bash untuk memeriksa kata berikutnya setelah alias (yaitu sudo) dengan menambahkan spasi ke akhir nilai alias.

Yesaya
sumber
18
Solusi yang cukup bagus.
ulidtko
Jadi pada dasarnya masalah ini bermuara pada fakta bahwa sudo hanya diprogram sedemikian rupa sehingga tidak memeriksa alias karena itu ll tidak ditemukan?
kemra102
2
Membaca dokumentasi jelas sangat bermanfaat :-)
biocyberman
4
Apakah ini akan pecah jika saya menggunakan bendera sudo, misalnya sudo -H ll?
Mark E. Haase
1
@mease Ya, saya mencoba dan itu rusak.
user31389
5

Saya menulis fungsi Bash untuk bayangan itu sudo.

Ia memeriksa apakah saya memiliki alias untuk perintah yang diberikan dan menjalankan perintah alias alih-alih yang literal dengan sudodalam kasus itu.

Inilah fungsi saya sebagai satu-liner:

sudo() { if alias "$1" &> /dev/null ; then $(type "$1" | sed -E 's/^.*`(.*).$/\1/') "${@:2}" ; else command sudo $@ ; fi }

Atau diformat dengan baik:

sudo() { 
    if alias "$1" &> /dev/null ; then 
        $(type "$1" | sed -E 's/^.*`(.*).$/\1/') "${@:2}"
    else 
        command sudo "$@"
    fi 
}

Anda dapat menambahkannya ke .bashrcfile Anda , jangan lupa untuk sumbernya atau mulai kembali sesi terminal Anda setelah itu untuk menerapkan perubahan.

Komandan Byte
sumber
Akan luar biasa jika ini juga akan bekerja untuk sudo -H ll.
uav
3

Alias ​​adalah khusus pengguna - Anda harus mendefinisikannya /root/.bashrc

Ragnar123
sumber
3
Mereka sudah di bawah /root/.bashrc jadi itu bukan masalah
kemra102
1
Jawaban ini hanya akan benar untuk situasi ketika Anda menjalankan shell itu sendiri sebagai root, seperti dengan sudo -satau sudo -i(dan hanya jika dijalankan dengan sendirinya untuk mendapatkan shell root, bukan dengan sudo -s command...atau sudo -i command...bentuk) atau sudo bashatau sudo su, atau situasi di mana Anda Sudah mengaktifkan login root dan memiliki shell root seperti itu. Ketika pengguna non-root berjalan sudo command...dari shell mereka sendiri, ekspansi alias dilakukan oleh shell non-root mereka sendiri. sudotidak dengan sendirinya memperluas alias, sehingga sebagaimana diterapkan pada situasi yang dijelaskan dalam pertanyaan , jawaban ini salah.
Eliah Kagan
3

@Alvins jawaban adalah yang terpendek. Tanpa keraguan! :-)

Namun saya memikirkan solusi baris perintah untuk mengeksekusi perintah alias di sudo di mana tidak perlu mendefinisikan ulang sudodengan aliasperintah.

Berikut adalah proposal saya untuk mereka yang tertarik:

Larutan

type -a <YOUR COMMAND HERE> | grep -o -P "(?<=\`).*(?=')" | xargs sudo

Contoh

Dalam hal llperintah

type -a ll | grep -o -P "(?<=\`).*(?=')" | xargs sudo

Penjelasan

ketika Anda memiliki alias (seperti :) llperintah type -amengembalikan ekspresi alias:

$type -a ll
ll is aliased to `ls -l'

dengan grepAnda memilih teks antara aksen `dan apostrof 'dalam kasus ituls -l

Dan xargsmengeksekusi teks yang dipilih ls -lsebagai parameter sudo.

Ya, sedikit lebih lama tetapi sepenuhnya bersih ;-) Tidak perlu mendefinisikan kembali sudosebagai alias.

dicintai.Yesus
sumber
3
Mungkin lebih sederhana jika Anda menggunakan aliasbuiltin, karena outputnya lebih bersih. alias lloutput alias ll='ls -ahlF'.
muru
Berikut versi menggabungkan saran @ Muru ini: alias ll | sed "s/.*'\(.*\)'.*/\1/g" | xargs sudo.
ACK_stoverflow
Saya pikir inti dari pertanyaan awal adalah untuk menyelamatkan pekerjaan dengan tidak harus sudo -iterlebih dahulu, untuk menjalankan perintah alias, tetapi langsung melakukannya. Memiliki perintah yang rumit mengalahkan itu. Anda bisa melakukan yang pertama, dan lebih cepat.
Evi1M4chine
1

Saya punya solusi bagus lain, yang menambahkan sedikit kepercayaan juga:

Gunakan penyelesaian bash untuk secara otomatis mengganti kata-kata di belakang sudodengan alias mereka saat menekan tab.

Simpan ini sebagai /etc/bash_completion.d/sudo-alias.bashcomp, dan itu akan secara otomatis dimuat pada startup shell interaktif:

_comp_sudo_alias() { from="$2"; COMPREPLY=()
  if [[ $COMP_CWORD == 1 ]]; then
    COMPREPLY=( "$( alias -p | grep "^ *alias $from=" | sed -r "s/^ *alias [^=]+='(.*)'$/\1/" )" )
    return 0
  fi
  return 1
}
complete -o bashdefault -o default -F _comp_sudo_alias sudo

Kemudian masuk ke terminal baru, dan Anda harus pergi dengan baik.

Evi1M4chine
sumber
Ada cara untuk mendapatkan daftar alias, terutama dimaksudkan untuk penyelesaian:compgen -a
muru
@uru: Terima kasih, tetapi dalam hal ini saya perlu nilai, bukan kunci. Jadi dengan apa alias yang dimasukkan akan diganti. Anda mengetik alias, (seperti dalam sudo ll), tekan [TAB ↹], dan skrip menemukan lldalam daftar tugas alias, memotong apa yang ditugaskan kepadanya, dan menyisipkan itu. (Jadi Anda akan mendapatkan mis sudo ls -lahvF --color=auto --time-style=long-iso.)
Evi1M4chine
0

Saya punya solusi berbeda di mana Anda tidak perlu menambahkan sudosebagai alias. Saya menjalankan Linux Mint 17.3 tetapi harus sangat mirip dengan Ubuntu.

Ketika Anda root, maka .profiledijalankan dari direktori home-nya. Jika Anda tidak tahu apa direktori home di bawah root, maka Anda dapat memeriksa:

sudo su
echo $HOME

Seperti yang Anda lihat, rumah rootitu /root/. Periksa isinya:

cd $HOME
ls -al

Seharusnya ada .profilefile. Buka file dan tambahkan baris berikut:

if [ "$BASH" ]; then
    if [ -f ~/.bash_aliases];then
        . ~/.bash_aliases 
    fi
fi

Pada dasarnya, apa yang dilakukan skrip bash ini adalah memeriksa file yang dipanggil .bash_aliases. Jika file ada, itu mengeksekusi file.

Simpan .profilefile dan buat alias Anda di .bash_aliases. Jika Anda sudah menyiapkan file alias, salin file ke lokasi ini

Luncurkan ulang terminal dan Anda siap berangkat!

Karthik Ramakrishnan
sumber
0

Jawaban terpilih teratas adalah jawaban yang bagus. Namun, jika Anda mengetik sudo -idan menaikkan ke sudo prompt ( #) Anda tidak akan memiliki alias yang ingin Anda gunakan.

Untuk memanfaatkan alias Anda (dan yang lainnya) saat #diminta, gunakan:

sudo cp "$PWD"/.bashrc /root/.bashrc

Di mana "$ PWD" diperluas secara otomatis ke "/ home / YOUR_USER_NAME"

WinEunuuchs2Unix
sumber
0

@ WinEunuuchs2Unix: $PWDmemperluas ke "direktori kerja sekarang". Saya pikir kamu mau $HOME.

Juga, untuk sebagian besar situasi, mungkin yang terbaik adalah memiliki file root .bashrc yang terpisah. Bahkan, saya akan membuatnya menjadi file nyata /root, tautan lunak untuk itu di direktori home pengguna (misalnya, .bashrc_root), dan sumber dari file pengguna .bashrc. Jika suatu saat nanti akun pengguna istimewa ini tidak lagi ada, .bashrcfile root masih tersedia untuk pengguna lain.

Shaun Griffith
sumber