Подтвердить что ты не робот

Выполнить оболочку script в текущей оболочке с разрешением sudo

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

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

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

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

Спасибо заранее.

4b9b3361

Ответ 1

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

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

Ответ 2

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

sudo bash script.sh

похоже, работает для меня.

Ответ 3

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

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

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


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

При поиске script не используется PATH и просто выполняется поиск пути. Обратите внимание, что source не является программой - иначе он не сможет изменить переменные среды в текущей оболочке. На самом деле это встроенная команда bash. Поиск /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.

Теперь наблюдайте, что происходит с bash:

> ./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

Ответ 4

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

Следовательно, ошибка.

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


Ответ 5

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

заменить оболочку на заданную программу (выполняющую ее, а не как новый процесс)

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

Рассмотрим этот контрольный пример и присмотритесь к pid 1337

# Don't worry, the content of this script is cat'ed below
$ ./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

$ 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

И более простой тест с использованием sudo -s

$ ./exec.sh
bash PID:25194    user ID:7809
systemd(1)───bash(23064)───bash(25194)───pstree(25196)

Finally...
bash PID:25199    user ID:0
systemd(1)───bash(23064)───sudo(25194)───bash(25199)───pstree(25201)

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

pid=$$
id=$(id -u)
echo "bash PID:$pid    user ID:$id"
pstree -ps $pid

# the quoted EOF is important to prevent shell expansion of the $...
exec sudo -s <<EOF
echo
echo "Finally..."
echo "bash PID:\$\$    user ID:\$(id -u)"
pstree -ps $pid
EOF

Ответ 6

Даже первый ответ абсолютно блестящий, вы, вероятно, хотите запускать скрипт только под sudo.

Вы должны указать абсолютный путь, например:

sudo /home/user/example.sh
sudo ~/example.sh

(оба работают)

ЭТО НЕ БУДЕТ РАБОТАТЬ!

sudo /bin/sh example.sh
sudo example.sh

Он всегда вернется

sudo: bin/sh: command not found
sudo: example.sh: command not found

Ответ 7

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

sudo /bin/sh example.sh