Передати функцію іншому користувачеві в 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.