bash 具有输入和管理权限的 Applescript 执行 Shell

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23905805/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 10:33:05  来源:igfitidea点击:

Applescript Execute Shell with Input and Admin Privileges

bashshellapplescript

提问by Vince Kronlein

I'm trying to write an automator service to fire up virtualhost.shin a terminal.

我正在尝试编写一个自动化服务来在终端中启动virtualhost.sh

Using the Services context menu the dialog opens to ask for the name of virtual host, then runs an applescript to launch terminal and pass in the input text.

使用服务上下文菜单打开对话框询问虚拟主机的名称,然后运行一个applescript 来启动终端并传入输入文本。

What I want is to pass in my username and password to admin privileges so that I don't need to pass it in the terminal with sudo.

我想要的是将我的用户名和密码传递给管理员权限,这样我就不需要在终端中使用 sudo 传递它。

This can be done with do shell scriptbut that executes a bin/shand the virtualhost.shis a bash script so I get the error bin/sh: virtualhost.sh command not found

这可以完成,do shell script但是执行 abin/sh并且virtualhost.sh是 bash 脚本,所以我收到错误bin/sh: virtualhost.sh command not found

Alternately I can use do script with commandbut this doesn't allow me to pass in the user name and password.

或者,我可以使用,do script with command但这不允许我输入用户名和密码。

My code looks like so:

我的代码看起来像这样:

on run {input, parameters}
    set vhost to "virtualhost.sh " & input
    tell application "Terminal"
        activate
        do shell script vhost user name "user" password "pass" with 
                  administrator privileges

    end tell
end run

This produces the bin/sh error previously mentioned.

这会产生前面提到的 bin/sh 错误。

With do script with command

do script with command

on run {input, parameters}
    set vhost to "virtualhost.sh " & input
    tell application "Terminal"
        activate
        do script with command vhost user name "user" password "pass" with
                  administrator privileges

    end tell
end run

This produces an escaping error: Expected end of line, etc. but found property.

这会产生一个转义错误:预期的行尾等,但找到了属性。

Is there a way to do this correctly?

有没有办法正确地做到这一点?

回答by Ivan X

Not specifically familiar with AppleScript Studio, but you can do it in plain old AppleScript (which appears to have the same issue) if you provide a full path to virtualhost.sh. (Also, Terminal is not required with "do shell script".) Example:

对 AppleScript Studio 不是特别熟悉,但如果您提供 virtualhost.sh 的完整路径,则可以使用普通的旧 AppleScript(似乎有相同的问题)来完成。(此外,“do shell script”不需要终端。)示例:

set vhost to "/usr/local/bin/virtualhost.sh " & input
do shell script vhost user name "user" password "pass" ?
    with administrator privileges

You can also extend $PATH (which is by default /usr/bin:/bin:/usr/sbin:/sbin with "do shell script") to include the path to virtualhost.sh, e.g.:

您还可以扩展 $PATH(默认为 /usr/bin:/bin:/usr/sbin:/sbin 并带有“do shell script”)以包含 virtualhost.sh 的路径,例如:

set vhost to "{ PATH=$PATH:/usr/local/bin; virtualhost.sh " & input & "; }"
do shell script vhost user name "user" password "pass" ?
    with administrator privileges

If you want a relative path, you can put virtualhost.sh inside the script application or bundle (e.g. in Contents/Resources), either in Terminal or by control-clicking and choosing "Show Package Contents". Then use "path to me":

如果您想要一个相对路径,您可以将 virtualhost.sh 放在脚本应用程序或包中(例如在内容/资源中),在终端中或通过按住 Control 单击并选择“显示包内容”。然后使用“我的路径”:

set vhostPath to "'" & POSIX path of (path to me) & ?
    "/Contents/Resources/virtualhost.sh" & "'"
set vhost to vhostPath & space & input
do shell script vhost user name "user" password "pass" ?
    with administrator privileges

回答by Ivan X

Per the comment on my other answer, I'm posting a secondary answer more in the spirit of that there's a will, there's a way, but it's a different, more dangerous approach. However, it's the only solution I can think of to this particular requirement (to get the interactivity of Terminal, but without having to prompt for an administrator password while running a script as administrator).

根据对我的其他答案的评论,本着有意愿、有办法的精神发布第二个答案,但这是一种不同的、更危险的方法。但是,这是我能想到的针对此特定要求的唯一解决方案(获得终端的交互性,但无需在以管理员身份运行脚本时提示输入管理员密码)。

This solution runs Terminal as root, which is what do shell script "command" with administrator privilegesdoes. This is dangerous because you have an open Terminal window with root access, so carefully weigh benefits against potential consequences of, say, opening a new Terminal window and being at the Bash prompt as root.

此解决方案以 root 身份运行终端,这就是do shell script "command" with administrator privileges它的作用。这是危险的,因为您有一个具有 root 访问权限的打开终端窗口,因此请仔细权衡好处与潜在后果,例如,打开一个新的终端窗口并以 root 身份在 Bash 提示符下。

For this reason, the Terminal instance that is opened is killed upon completion of the script; if the "kill" command is removed, be aware you'll get multiple instances of Terminal, rather than multiple windows within the same instance.

出于这个原因,打开的终端实例在脚本完成时被杀死;如果删除了“kill”命令,请注意您将获得多个终端实例,而不是同一实例中的多个窗口。

No idea if this works in AppleScript Studio (it works in AppleScript Editor), but I can't think of any reason why it wouldn't.

不知道这是否适用于 AppleScript Studio(它适用于 AppleScript 编辑器),但我想不出任何原因。

set input to "some_input"
set vhost to "/usr/local/bin/virtualhost.sh " & input
set kill to ?
    "terminal_pid=$(</tmp/terminal_pid); rm /tmp/terminal_pid; kill $terminal_pid"

-- launch Terminal as root, and save its process ID in /tmp/terminal_pid
tell application "Finder" to set beforeProcesses to processes
do shell script ?
    "/Applications/Utilities/Terminal.app/Contents/MacOS/Terminal " & ?
    "&> /dev/null & echo $! > /tmp/terminal_pid" user name "user" password ?
    "pass" with administrator privileges

-- wait until the new Terminal is confirmed to be running
tell application "Finder"
    repeat while (processes is equal to beforeProcesses)
        do shell script "sleep 0.5"
    end repeat
end tell

-- Perform script in root Terminal window that we just opened,
-- and kill Terminal when done to prevent open root prompt
-- and multiple processes.
tell application "Terminal"
    activate
    do script vhost & "; " & kill
end tell

-- optional: wait until Terminal is gone before continuing
do shell script "while [[ ( -f /tmp/terminal_pid ) " & ?
    "&& ( \"$(ps -p $(</tmp/terminal_pid) -o%cpu='')\" ) ]]; do sleep 0.5; done"