2016-12-20 5 views
0

У меня есть сценарий, который копирует файлы между серверами. Я использую команду lsof, чтобы убедиться, что файл не записывается перед перемещением. Пользователь, запускающий скрипт и пользователь, записывающий в файл, отличается, поэтому мне нужно sudo для владельца файла. Вот соответствующая строка в файле sudoers:Использовать источник со скриптом, который содержит команду sudo

userA ALL=(userB:userB) NOPASSWD: ALL 

В главном скрипте (бежал как ПользовательА), я попытался назвать SUDO то индекс, содержащий команду LSOF:

sudo su - userB -c 'source ./getOpenFiles.sh' 

getOpenFiles.sh имеет одну строку:

#!/bin/bash 
lsofResult=$(/usr/sbin/lsof "${sourcePath}") 

Я также попытался назвать индекс:

source ./getOpenFiles.sh 

Тогда есть первая линия подстрочный быть Sudo:

#!/bin/bash 
sudo su - banjobs 
lsofResult=$(/usr/sbin/lsof "${sourcePath}")`. 

Ни одно из решений работает.

+0

Когда вы запускаете 'sudo su - banjobs', следующая команда не запускается до тех пор, пока ваш' sudo su' не завершится и не выйдет, и ничего не осталось, как 'banjobs'. –

+0

Это означает, что он не оценивает 'lsofResult' как' banjobs'. –

+0

... и если вы используете 'su -c 'source somescript'', то' somescript' запускается 'sh', а не' bash', независимо от того, что говорит его shebang. И если ваш 'sh' не поддерживает' source', то он не запускается вообще. (POSIX-совместимый способ записи 'source' -'. Somescript', а не 'source somescript'). –

ответ

1

То, что вы на самом деле хотите что-то подобное:

lsofResult=$(sudo -u banjobs lsof "${sourcePath}") 

Давайте рассмотрим, почему другие подходы не работают один-на-времени:

  • Запуск source под sudo su -c

    sudo su - userB -c 'source ./getOpenFiles.sh' 
    

    ... использует sudo для запуска su, который работает sh -c 'source ./getOpenFiles.sh'. Это не работает по нескольким независимым причинам:

    1. sh -c 'source ./getOpenFiles.sh' опирается на source ключевое слово в наличии в /bin/sh, но это расширение Баш.

    2. Даже если ваш /bin/sh обеспечивается Баш, это по-прежнему побеждает цель использования source: При запуске новой копии /bin/sh и снабжаем свой сценарий в том, что вы определяете переменную в новую оболочку, не в оригинальной раковине, которая началась sudo su.

  • Запуск sudo su - banjobs, а затем lsofResult=$(/usr/sbin/lsof "${sourcePath}")

    ... означает, что lsofResult=$(...) не не работает до тех пор, после sudo su - banjobs выходов. Если sudo su - banjobs вышел, то текущий пользователь уже не banjobs, поэтому команда sudo не имеет никакого эффекта на lsof.


Показательными, подробно, как проверить это (для людей, которые не имеют banoff или userB счетов на их системе):

# place relevant contents in sourceme.bash 
# switching from lsof to fuser for this test since OS X lsof does not accept a directory 
# as an argument. 
cat >sourceme.bash <<'EOF' 
lsofResult=$(sudo -u root fuser "${sourcePath}" 2>&1) 
EOF 

# set sourcePath in the outer shell 
sourcePath=$PWD 
source sourceme.bash 
declare -p lsofResult 

... урожайности, на моя система, выход сродни следующему:

declare -- lsofResult="/Users/chaduffy/tmp: 17165c 17686c 17687c 17688c 17689c 17690c" 

... показывая, что данный код действительно работал как описано.

+0

Спасибо за ваш ответ Чарльз. К сожалению, ваше решение все еще не работает. Я попробовал его как в индексе, так и в главном скрипте. – Stu

+0

@Stu, мне нужно будет увидеть полный репродуцир, точно показывающий *, как вы его используете (как вызов, так и оценка собранного значения). Это, безусловно, «работает» при правильном использовании - я рад изменить пример в вопросе, показывающем это. –

+0

@Stu, ... такой пример был добавлен. –