Mengirimkan Fungsi ke pengguna lain di Bash?

11

Apakah ada cara agar saya dapat meneruskan suatu Fungsi dari satu pengguna ke pengguna lain?

Misalnya, saya memiliki skrip Bash kecil yang saya jalankan sebagai Root:

#!/bin/bash
user_func(){
  whoami
  exit
}
su vagrant -c 'user_func'

Namun, Fungsi user_func tidak ditentukan untuk pengguna Vagrant, hanya untuk Root, dan tidak dapat dijalankan.

Opsi saya yang lain adalah memiliki beberapa baris

su vagrant -c 'cmd1' 
su vagrant -c 'cmd2'
, etc 

Atau, jalankan beberapa perintah, misalnya:, su vagrant -c 'cmd1; cmd2; cmd3;'tapi saya lebih suka tidak memiliki kelebihan, terutama ketika mencoba menjalankan lebih dari 5 perintah sebagai pengguna Vagrant.

Apakah mungkin untuk meneruskan Fungsi ke pengguna lain dari dalam skrip yang sama (mis. Tidak membuat skrip pada disk sebagai pengguna yang berbeda dan kemudian menjalankan skrip yang dihasilkan)? Atau adakah pilihan lain yang saya abaikan?

gdieckmann
sumber

Jawaban:

10

Kedengarannya Anda perlu exportdefinisi fungsi itu terlebih dahulu:

#!/bin/bash
user_func (){
  whoami
  exit
}
export -f user_func
su vagrant -c 'user_func'

harus melakukan trik.

The -fmemberitahu exportbahwa ini adalah nama fungsi daripada nama variabel. Mengutip dari help export:

Tandai setiap NAME untuk ekspor otomatis ke lingkungan perintah yang dieksekusi selanjutnya. ....

Pilihan:

 -f   refer to shell functions

Seperti yang ditunjukkan oleh peterph dan Stephane dalam komentar, ini mengasumsikan dua hal:

  1. Bahwa superintah Anda tidak akan menimpa lingkungan pengguna
  2. Itu vagrantadalah shell login bash. Jika tidak, Anda dapat menggunakan subaris perintah alternatif yang disediakan oleh Stephane:

    su vagrant -c 'bash -c user_func'
Joseph R.
sumber
Ini sebenarnya yang saya harapkan. Saya tidak menyadari bahwa Anda dapat mengekspor fungsinya. Ini berfungsi seperti yang saya harapkan setelah mengedit skrip sampel. Terima kasih!
gdieckmann
1
Bagus, tetapi tidak akan berfungsi dalam kasus di mana sumenimpa lingkungan.
peterph
1
Perhatikan bahwa ini hanya berfungsi jika shell login vagrantis bash. Jika tidak,su vagrant -c 'bash -c user_func'
Stéphane Chazelas
6

Ini agak meretas, tetapi Anda dapat mencetak definisi fungsi di dalam perintah yang diteruskan sudan tentu saja Anda dapat menggunakannya.

$ function foo { do_some_stuff_here; }
$ su test -c "$(typeset -f foo); foo"

Ini akan berfungsi bahkan jika karena alasan tertentu lingkungan shell yang sudihasilkan akan ditimpa, karena ia meletakkan definisi setelah inisialisasi shell. Jika Anda menulis fungsi ini cukup kompatibel, itu bahkan akan berfungsi ketika dua pengguna yang bersangkutan menggunakan cangkang yang berbeda.

peterph
sumber
+1 Trik yang benar-benar rapi! Hanya sebuah pertanyaan, dapatkah lingkungan sushell ditimpa oleh faktor-faktor eksternal? Maksud saya, dalam hal ini Anda memiliki kontrol penuh atas subaris perintah karena itu dalam skrip. Bagaimana lingkungan shell yang baru ditimpa?
Joseph R.
Misalnya shell yang dihasilkan sumungkin melakukan inisialisasi lingkungan. Juga suitu sendiri mungkin menghapus beberapa lingkungan penelepon untuk sedikit memperketat keamanan (meskipun ini biasanya dilakukan oleh alternatif yang lebih kuat seperti sudo).
peterph
0

Itu bukan skrip yang Anda miliki, ini sebuah fungsi. Tapi sepertinya Anda menginginkan skrip. Buat skrip yang tepat dan letakkan, sesuai kebutuhan Anda, baik di dalam /usr/local/bin, atau di dalam /home/vagrant/bin, dan daripada yang seharusnya bisa Anda lakukansu vagrant -c '/home/vagrant/bin/myscript.sh'

DopeGhoti
sumber
Ini adalah fungsi dalam skrip sampel. Harapan saya adalah memasukkan semua yang ingin saya lakukan di dalam skrip tunggal ini (perintah dijalankan sebagai Root, dan sebagai pengguna Vagrant), dan tidak harus memiliki skrip terpisah untuk pengguna Root dan skrip terpisah untuk pengguna Vagrant.
gdieckmann
0

Cara lain yang agak lebih portabel untuk melakukan ini (tanpa ketergantungan bash) adalah membuat skrip memanggil dirinya sendiri dan mengubah perilakunya berdasarkan konteks (uid) atau parameter. contoh dari ini diberikan dalam dokumentasi di supermana mereka menunjukkan skrip yang membutuhkan izin root, memanggil dirinya sendiri melalui super ketika tidak melakukan root.

Hildred
sumber