2013-09-15 2 views
25

Для выполнения сценария оболочки в текущей оболочке нам нужно использовать период . или команду source. Но почему это не работает с разрешением sudo?Выполнение сценария оболочки в текущей оболочке с разрешением sudo

У меня есть сценарий с разрешением на выполнение setup.sh. Когда я использую период, я получаю следующее:

$ sudo . ./setup.sh 
sudo: .: command not found 

Команда источника также производит аналогичную ошибку. Я что-то упускаю? Что делать, чтобы запустить скрипт с разрешением sudo в той же оболочке?

Заранее спасибо ..

+0

Несмотря на отличные ответы, я думаю, что проблема почти опечатка.Удалите первый период, который сам по себе. – beroe

+0

@beroe Вы ошибаетесь. Проблема не опечатка. Если 'setup.sh' не имеет прав выполнения, то вы должны явно интерпретировать его с помощью bash. Это можно сделать как 'bash setup.sh' или' source setup.sh' или '. setup.sh'. Однако, поскольку последние 2 являются встроенными bash, только 1-я форма может использоваться с ** sudo **, которая ** требует исполняемого файла **. Вы можете использовать 'sudo, которые bash' и' sudo, какой источник' и 'sudo which .', чтобы увидеть, что' sudo' найдет. –

+0

@BrunoBronosky это выглядело (выглядит), как будто они пытаются запустить первую одиночную точку в качестве команды. Поскольку это указывает текущий рабочий каталог, который не является командой, он выдает эту ошибку. Если они поместите './Setup.sh', это будет другая история. – beroe

ответ

25

То, что вы пытаетесь сделать, это невозможно; ваша текущая оболочка работает под вашим обычным идентификатором пользователя (т. е. без права доступа, доступ к которому вы получите sudo), и нет способа предоставить ему root-доступ. То, что делает sudo, - это создать новый * югу * процесс, который выполняется как root. Подпроцессом может быть только обычная программа (например, sudo cp ... запускает программу cp в корневом процессе), или это может быть корневая подоболочка, но не может быть текущей оболочкой.

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

+1

Я не уверен, почему это принятый ответ, когда, как мне кажется, работает для меня ответ @ JaseC. sudo bash myscript.sh делает именно то, что я искал, и то, о чем, казалось, спрашивал OP. – russell

+8

@dalesikkema: 'sudo bash myscript.sh' запустит скрипт в подоболочке, а не в текущей оболочке. Если это работает в вашей ситуации, отлично, но этот конкретный вопрос заключается в том, чтобы запустить скрипт как root * в текущей оболочке *. –

+1

Вся предпосылка двусмысленности из-за неверного выбора слова. «Для выполнения сценария оболочки в текущей оболочке нам нужно использовать период« Нет, этот период не выполняется, он содержит источники, вставляет, читает или интерпретирует. Выполнение подразумевает разрозненный PID. Итак, мы неясны, если/почему они могут заботиться о PID своей текущей оболочки. –

3

В основном Судо ожидает, исполняемым (команда), чтобы следовать & вы обеспечиваете с .

Отсюда возникает ошибка.

Попробуйте этому путь $ sudo setup.sh


+0

, но sudo sh setup.sh создает новую оболочку для выполнения скрипта. Я хочу выполнить в той же оболочке. – shar

+0

тогда 'sudo setup.sh' должен работать. – loxxy

+2

Но для этого требуется, чтобы setup.sh находился в PATH. – shar

26

Я думаю, что вы смущены о разнице между поиском и выполнением сценария.

Выполнение скрипта означает создание нового процесса и запуск программы. Программа может быть сценарием оболочки или любым другим типом программы. Поскольку это подпроцесс, любые переменные среды, измененные в программе, не будут влиять на оболочку.

Поиск сценария может использоваться только с помощью сценария bash (если вы используете bash). Он эффективно вводит команды так, как если бы вы их делали. Это полезно, поскольку позволяет сценарию изменять переменные среды в оболочке.


Запуск сценария прост, вы просто вводите путь к скрипту. . - текущий каталог. Таким образом, ./script.sh выполнит файл script.sh в текущей директории. Если команда является одним файлом (например, script.sh), она проверит все папки в переменной PATH, чтобы найти скрипт. Обратите внимание, что текущий каталог не находится в PATH, поэтому вы не можете выполнить файл script.sh в текущем каталоге, запустив script.sh, вам нужно запустить ./script.sh (если текущий каталог не находится в PATH, например, вы можете запустить ls, в то время как в /bin).

Поиск сценария не использует PATH и просто ищет путь. Обратите внимание, что source не является программой - иначе она не сможет изменить переменные среды в текущей оболочке. На самом деле это баш, встроенный в команду. Поиск /bin и /usr/bin - вы не найдете здесь программу source. Поэтому для источника файла script.sh в текущем каталоге вы просто используете source script.sh.


Как sudo взаимодействует с этим? Ну sudo берет программу и выполняет ее как root. Например, sudo ./script.sh выполняет script.sh в подпроцессе, но работает от имени root.

Что же делает sudo source ./script.sh? Помните, что source - это не программа (скорее, встроенная оболочка)? Sudo ожидает название программы, поэтому ищет программу с именем source.Он не находит его, и так не получается. Невозможно запустить файл с правами root, не создавая новый подпроцесс, так как вы не можете изменить бегун программы (в данном случае bash) после ее запуска.

Я не уверен, что вы на самом деле хотели, но, надеюсь, это очистит его для вас.


Вот конкретный пример. Сделайте файл script.sh в текущем каталоге с содержимым:

#!/bin/bash  
export NEW_VAR="hello" 
whoami 
echo "Some text" 

сделать его исполняемым с chmod +x script.sh.

Теперь посмотрим, что происходит с Баш:

> ./script.sh 
david 
Some text 
> echo $NEW_VAR 

> sudo ./script.sh 
root 
Some text 
> echo $NEW_VAR 

> source script.sh 
david 
Some text 
> echo $NEW_VAR 
hello 
> sudo source script.sh 
sudo: source: command not found 
66

Я не уверен, если это нарушает какие-либо правила, но

sudo bash script.sh 

, кажется, работает для меня.

+0

+1 но в чем причина этого? – Anconia

+1

Я думаю, потому что вы создаете оболочку с правами root и запускаете скрипт внутри нее. – JaseC

+0

Это точный ответ на вопрос –

1

Если вы действительно хотите, чтобы « Выполнить вызвать скрипт оболочки в текущей оболочке с разрешением SUDO» вы можете использовать exec для ...

replace the shell with a given program (executing it, not as new process)

Я настаиваю на замене " выполнить "с" вызовом ", потому что первое имеет значение, которое включает в себя создание нового процесса и идентификатора, где последнее является неоднозначным и оставляет место для творчества, из которых я заполнен.

Рассмотрим этот тест, и внимательно посмотреть на ВЗОМТ

$ ./test.sh -o foo -p bar 

User ubuntu is running... 
PID TT  USER  COMMAND 
775 pts/1 ubuntu -bash 
1408 pts/1 ubuntu \_ bash ./test.sh -o foo -p bar 
1411 pts/1 ubuntu  \_ ps -t /dev/pts/1 -fo pid,tty,user,args 

User root is running... 
PID TT  USER  COMMAND 
775 pts/1 ubuntu -bash 
1337 pts/1 root  \_ sudo ./test.sh -o foo -p bar 
1412 pts/1 root   \_ bash ./test.sh -o foo -p bar 
1415 pts/1 root    \_ ps -t /dev/pts/1 -fo pid,tty,user,args 

Take 'exec' out of the command and this script would get cat-ed twice. (Try it.) 

#!/usr/bin/env bash 

echo; echo "User $(whoami) is running..." 
ps -t $(tty) -fo pid,tty,user,args 

if [[ $EUID > 0 ]]; then 
    # exec replaces the current process effectively ending execution so no exit is needed. 
    exec sudo "$0" "[email protected]" 
fi 

echo; echo "Take 'exec' out of the command and this script would get cat-ed twice. (Try it.)"; echo 
cat $0 

Вот еще один тест с использованием sudo -s

$ ps -fo pid,tty,user,args; ./test2.sh 
    PID TT  USER  COMMAND 
10775 pts/1 ubuntu -bash 
11496 pts/1 ubuntu \_ ps -fo pid,tty,user,args 

User ubuntu is running... 
    PID TT  USER  COMMAND 
10775 pts/1 ubuntu -bash 
11497 pts/1 ubuntu \_ bash ./test2.sh 
11500 pts/1 ubuntu  \_ ps -fo pid,tty,user,args 

User root is running... 
    PID TT  USER  COMMAND 
11497 pts/1 root  sudo -s 
11501 pts/1 root  \_ /bin/bash 
11503 pts/1 root   \_ ps -fo pid,tty,user,args 

Finally... 
Another example using UID: 0 

$ cat test2.src 
echo; echo "User $(whoami) is running..." 
ps -fo pid,tty,user,args 

$ cat test2.sh 
#!/usr/bin/env bash 

source test2.src 

exec sudo -s < test2.src 

# NOTE: Only one 'exec' will run. I'm faking the output to combine 2 runs 

# the quoted EOF is important to prevent shell expansion of the $... 
exec sudo -s <<'EOF' 
echo; echo "Finally..."; echo "Another example using UID: $(id -u)" 
EOF 
-1

Самый простой способ набрать:

  • sudo /bin/sh example.sh
Смежные вопросы