Linux 使用 sudo 权限在当前 shell 中执行 shell 脚本
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18809614/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Execute a shell script in current shell with sudo permission
提问by shar
For executing a shell script in current shell, we need to use a period .
or a source
command. But why does it not work with a sudo permission?
要在当前 shell 中执行 shell 脚本,我们需要使用句点.
或source
命令。但是为什么它在 sudo 权限下不起作用?
I have a script with execute permission called setup.sh
. When I use a period, I get this:
我有一个名为setup.sh
. 当我使用一段时间时,我得到了这个:
$ sudo . ./setup.sh
sudo: .: command not found
The source command also produces a similar error. Am I missing out something? What should I do to run the script with sudo permission in the same shell?
source 命令也会产生类似的错误。我错过了什么吗?我应该怎么做才能在同一个 shell 中以 sudo 权限运行脚本?
Thanks in advance..
提前致谢..
采纳答案by Gordon Davisson
What you are trying to do is impossible; your current shell is running under your regular user ID (i.e. without root the access sudo
would give you), and there is no way to grant it root access. What sudo
does is create a new *sub*process that runs as root. The subprocess could be just a regular program (e.g. sudo cp ...
runs the cp
program in a root process) or it could be a root subshell, but it cannotbe the current shell.
你试图做的事情是不可能的;您当前的 shell 正在您的常规用户 ID 下运行(即没有 root 访问权限sudo
会给您),并且无法授予它 root 访问权限。什么sudo
是创建一个以 root 身份运行的新 *sub*process。子进程可以只是一个常规程序(例如在根进程中sudo cp ...
运行该cp
程序)或者它可以是一个根子shell,但它不能是当前的shell。
(It's actually even more impossible than that, because the sudo
command itself is executed as a subprocess of the current shell -- meaning that in a sense it's already too late for it to do anything in the "current shell", because that's not where it executes.)
(实际上比这更不可能,因为sudo
命令本身是作为当前 shell 的子进程执行的——这意味着从某种意义上说,它在“当前 shell”中做任何事情已经太晚了,因为那不是它的位置执行。)
回答by loxxy
Basically sudo expects, an executable (command) to follow & you are providing with a .
基本上 sudo 期望,要遵循的可执行文件(命令)并且您正在提供 .
Hence the error.
因此错误。
Try this way $ sudo setup.sh
试试这个方法 $ sudo setup.sh
回答by David Miani
I think you are confused about the difference between sourcing and executing a script.
我认为您对采购和执行脚本之间的区别感到困惑。
Executing a script means creating a new process, and running the program. The program can be a shell script, or any other type of program. As it is a sub process, any environmental variables changed in the program will not affect the shell.
执行脚本意味着创建一个新进程并运行该程序。该程序可以是 shell 脚本,也可以是任何其他类型的程序。由于它是一个子进程,因此程序中更改的任何环境变量都不会影响shell。
Sourcing a script can only be used with a bash script (if you are running bash). It effectively types the commands in as if you did them. This is useful as it lets a script change environmental variables in the shell.
采购脚本只能与 bash 脚本一起使用(如果您正在运行 bash)。它有效地输入命令,就像你输入它们一样。这很有用,因为它允许脚本更改 shell 中的环境变量。
Running a script is simple, you just type in the path to the script. .
is the current directory. So ./script.sh
will execute the file script.sh
in the current directory. If the command is a single file (eg script.sh
), it will check all the folders in the PATH variable to find the script. Note that the current directory isn't in PATH, so you can't execute a file script.sh
in the current directory by running script.sh
, you need to run ./script.sh
(unless the current directory is in the PATH, eg you can run ls
while in the /bin
dir).
运行脚本很简单,您只需输入脚本的路径即可。.
是当前目录。所以./script.sh
会执行script.sh
当前目录下的文件。如果命令是单个文件(例如script.sh
),它将检查 PATH 变量中的所有文件夹以查找脚本。请注意,当前目录不在 PATH 中,因此您不能通过script.sh
运行script.sh
来执行当前目录中的文件,您需要运行./script.sh
(除非当前目录在 PATH 中,例如您可以ls
在/bin
dir 中运行)。
Sourcing a script doesn't use the PATH, and just searches for the path. Note that source
isn't a program - otherwise it wouldn't be able to change environmental variables in the current shell. It is actually a bash built in command. Search /bin
and /usr/bin
- you won't find a source
program there. So to source a file script.sh
in the current directory, you just use source script.sh
.
获取脚本不使用 PATH,而只是搜索路径。请注意,这source
不是程序 - 否则它将无法更改当前 shell 中的环境变量。它实际上是一个内置命令的 bash。搜索/bin
和/usr/bin
- 你不会在source
那里找到一个程序。因此,要script.sh
在当前目录中获取文件,您只需使用source script.sh
.
How does sudo interact with this? Well sudo takes a program, and executes it as root. Eg sudo ./script.sh
executes script.sh
in a sub process but running as root.
sudo 如何与此交互?那么 sudo 需要一个程序,并以 root 身份执行它。例如,在子进程中sudo ./script.sh
执行script.sh
但以 root 身份运行。
What does sudo source ./script.sh
do however? Remember source
isn't a program (rather a shell builtin)? Sudo expects a program name though, so it searches for a program named source
. It doesn't find one, and so fails. It isn't possible to source a file running as root, without creating a new subprocess, as you cannot change the runner of a program (in this case, bash) after it has started.
sudo source ./script.sh
但是有什么作用呢?记住source
不是一个程序(而是一个内置的shell)?不过,Sudo 需要一个程序名称,因此它搜索名为source
. 它没有找到,所以失败了。不可能在不创建新子进程的情况下获取以 root 身份运行的文件,因为您无法在程序启动后更改运行程序(在本例中为 bash)。
I'm not sure what you actually wanted, but hopefully this will clear it up for you.
我不确定您真正想要什么,但希望这会为您解决问题。
Here is a concrete example. Make the file script.sh
in your current directory with the contents:
这是一个具体的例子。script.sh
使用以下内容在当前目录中创建文件:
#!/bin/bash
export NEW_VAR="hello"
whoami
echo "Some text"
Make it executable with chmod +x script.sh
.
使用chmod +x script.sh
.
Now observe what happens with bash:
现在观察 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
回答by JaseC
I'm not sure if this breaks any rules but
我不确定这是否违反任何规则,但是
sudo bash script.sh
seems to work for me.
似乎对我有用。
回答by Bruno Bronosky
If you really want to "ExecuteCall a shell script in current shell with sudo permission" you can use exec
to...
如果您真的想“使用 sudo 权限在当前 shell 中执行调用 shell 脚本”,您可以使用exec
...
replace the shell with a given program (executing it, not as new process)
I insist on replacing "execute" with "call" because the former has a meaning that includes creating a new process and ID, where the latter is ambiguous and leaves room for creativity, of which I am full.
我坚持用“调用”代替“执行”,因为前者的含义包括创建一个新的进程和ID,后者是模棱两可的,留下了创造力的空间,我对此很满意。
Consider this test case and look closely at pid 1337
考虑这个测试用例并仔细查看 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 "$ 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
" "$@"
fi
echo; echo "Take 'exec' out of the command and this script would get cat-ed twice. (Try it.)"; echo
cat $ ./exec.sh
bash's PID:25194 user ID:7809
systemd(1)───bash(23064)───bash(25194)───pstree(25196)
Finally...
bash's 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's 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's PID:$$ user ID:$(id -u)"
pstree -ps $pid
EOF
Here is another test using sudo -s
这是另一个测试使用 sudo -s
sudo /bin/sh example.sh
And a simpler test using sudo -s
和一个更简单的测试使用 sudo -s
sudo /home/user/example.sh
sudo ~/example.sh
回答by Simon Hayter
Easiest method is to type:
最简单的方法是键入:
sudo /bin/sh example.sh
sudo example.sh
回答by Martin Kova?
Even the first answer is absolutely brilliant, you probably want to only run script under sudo.
即使第一个答案绝对精彩,您可能只想在 sudo 下运行脚本。
You have to specify the absolute path like:
您必须指定绝对路径,例如:
sudo: bin/sh: command not found
sudo: example.sh: command not found
(both are working)
(两人都在工作)
THIS WONT WORK!
这行不通!
sensitive_stuff=$(sudo cat ".env")
eval "${sensitive_stuff}"
echo $ADMIN_PASSWORD
It will always return
它总会回来
##代码##回答by Ohiovr
The answers here explain why it happens but I thought I'd add my simple way around the issue. First you can cat the file into a variable with sudo permissions. Then you can evaluate the variable to execute the code in the file in your current shell.
这里的答案解释了为什么会发生这种情况,但我想我会添加解决这个问题的简单方法。首先,您可以将文件转换为具有 sudo 权限的变量。然后,您可以评估变量以在当前 shell 中执行文件中的代码。
Here is an example of reading and executing an .env file (ex Docker)
这是读取和执行 .env 文件的示例(例如 Docker)
##代码##