Передати функцію іншому користувачеві в Bash?


11

Чи є спосіб передати функцію від одного користувача до іншого користувача?

Наприклад, у мене є невеликий сценарій Bash, який я виконую як Root:

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

Однак функція user_func не визначена для користувача Vagrant, лише для Root, і не може бути виконана.

Моїм іншим варіантом було б мати кілька рядків

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

Або виконати кілька команд ех: su vagrant -c 'cmd1; cmd2; cmd3;', але я не хотів би мати надлишок, особливо при спробі виконати більше 5 команд , як користувач Vagrant.

Чи можливо передати функцію іншому користувачеві в межах одного сценарію (наприклад, не створити сценарій на диску як інший користувач, а потім виконати створений сценарій)? Або є інший варіант, який я оглядаю?

Відповіді:


10

Здається, що вам потрібно спочатку визначити exportцю функцію:

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

повинен зробити трюк.

-fКаже , exportщо це ім'я функції , а не ім'я змінної. Цитуючи help export:

Позначає кожне NAME для автоматичного експорту в середовище згодом виконаних команд. ….

Параметри:

 -f   refer to shell functions

Як в коментарях вказували Петерф і Стефан, це передбачає дві речі:

  1. Щоб ваша suкоманда не замінювала середовище користувача
  2. Це vagrantоболонка для входу bash. Якщо ні, ви можете використовувати альтернативний suкомандний рядок, наданий Stephane:

    su vagrant -c 'bash -c user_func'

Це насправді саме те, на що я сподівався. Я не розумів, що ви зможете експортувати цю функцію. Це спрацювало так само, як я сподівався, що це буде після редагування зразкового сценарію. Спасибі!
gdieckmann

1
Приємно, але не вийде у випадках, коли suперекриває навколишнє середовище.
петерф

1
Зауважте, що вона працює лише в тому випадку, якщо оболонка входу vagrantє bash. Якщо ні,su vagrant -c 'bash -c user_func'
Стефан Шазелас

6

Це трохи хакітно, але ви можете надрукувати визначення функції всередині переданого соманду, suа потім, звичайно, можете ним скористатися.

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

Це буде працювати, навіть якщо з якихось причин середовище, породжене оболонкою, suбуде перезаписано, оскільки воно ставить визначення після ініціалізації оболонки. Якщо ви напишете функцію досить сумісно, ​​вона буде працювати навіть тоді, коли ці два користувачі використовують різні оболонки.


+1 Дійсно акуратний трюк! Лише питання, чи може середовище suоболонки переписати зовнішні фактори? Я маю на увазі, в цьому випадку ви маєте повний контроль над suкомандним рядком, оскільки він знаходиться в сценарії. Як можна замінити нове середовище оболонки?
Джозеф Р.

Наприклад, оболонка, породжена якою, suможе зробити ініціалізацію середовища. Також suсама може позбавити деякого оточення абонента, щоб трохи посилити безпеку (хоча це зазвичай роблять більш потужні альтернативи, як-от sudo).
петерф

0

Це не сценарій у вас є, це функція. Але це здається, що ви хочете сценарію. Складіть належний сценарій і поставте його, як того вимагають ваші потреби, або в /usr/local/bin, або в /home/vagrant/bin, і ніж ви повинні мати можливість, наприкладsu vagrant -c '/home/vagrant/bin/myscript.sh'


Це функція в зразковому сценарії. Я сподівався включити все, що я хочу зробити в рамках цього єдиного сценарію (команди виконуються як Root, так і як користувач Vagrant), а не мати окремий скрипт для користувача Root та окремий сценарій для користувача Vagrant.
gdieckmann

0

Ще один більш портативний спосіб зробити це (без баш-залежності) - це змусити ваш сценарій викликати себе і змінити його поведінку залежно від контексту (uid) або параметрів. приклади цього наведені в документації, superде вони показують сценарій, який потребує дозволів root, називаючи його self через super, а не root.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.