【问题标题】:ipython: Can I provide input to a shell commandipython:我可以为 shell 命令提供输入吗
【发布时间】:2013-09-20 00:28:42
【问题描述】:

我可以执行需要在 ipython 和/或 ipython 笔记本中输入的 shell 命令吗?

当我执行这样的命令时,我看到它是提示符,但没有明显的方法可以从我的键盘向它提供输入。

一个例子可以是对远程服务器的rsync 命令(因此需要密码)。毫无疑问,这里存在安全方面的危险 - 在我的情况下,这些风险有所减少,因为我在 localhost 上运行。

【问题讨论】:

标签: shell ipython ipython-notebook


【解决方案1】:

转贴作为答案,更详细一点:

不,这是一个很难解决的长期问题:github.com/ipython/ipython/issues/514

问题大致是我们的架构无法判断进程何时等待输入,因此它不知道提示用户输入。

您可以使用 pexpect 和 raw_input 来模拟特定程序的情况。 IE。如果您说出提示的样子,它会在输出中发现它,并要求用户输入以发送回流程。例如。对于 Python:

import pexpect
p = pexpect.spawn('python')
while True:
    try:
        p.expect('\n>>> ')
        print(p.before)
        p.sendline(raw_input('>>> '))
    except pexpect.EOF:
        break

我刚刚对此进行了简短的测试 - 它有效,但相当粗糙。这个概念可以改进。

【讨论】:

    【解决方案2】:

    很遗憾,没有。

    我找不到这方面的文档,所以我去源头潜水。实际执行该转换的 ipython 代码是 https://github.com/ipython/ipython/blob/master/IPython/core/inputtransformer.py#L208 ,具体来说:

    def _tr_system(line_info):
        "Translate lines escaped with: !"
        cmd = line_info.line.lstrip().lstrip(ESC_SHELL)
        return '%sget_ipython().system(%r)' % (line_info.pre, cmd)
    

    换句话说,它使用! 之后的所有内容调用底层shell。

    ipython 可能不是您想要的——请查看 this answer 以获取要包含在脚本中的 Python 替代品。

    【讨论】:

      【解决方案3】:

      我只是在寻找这个,当我看到它有点问题时,我的小脸掉了下来。以为我会发布我的解决方案,以防它对其他人有用。

      基本上,我正在寻找一种通过笔记本发送sudo 命令的方法,这可能不是很明智,但我需要它来完成我的工作。而且我无法提示输入密码。因此决定使用x-terminal 并将命令发送到终端。您没有得到任何反馈,但可能是由于在返回的路上没有连接到 IO。这是我在笔记本中使用的:

      在[1]!xterm -e sudo mount -o loop system.img /system/

      我正在使用 linux,但我希望 !cmd for windows 也可以解决问题

      【讨论】:

      • 好主意,完全绕过 jupyter!我想我在关于 sudo 和 askpass 的回答中找到了您可能更喜欢的一个。
      【解决方案4】:

      许多需要密码的程序提供了多种方式来提示用户输入密码,这样jupyter 就不必为您输入密码。 sudo 命令有一个-A 选项和SUDO_ASKPASS 环境变量。我已经像这样使用它来使用 sudo 来获取/var/log/btmp.1 文件的权限:

       In [1]: !SUDO_ASKPASS=/usr/bin/ssh-askpass sudo -A lastb -a -f /var/log/btmp.1 | head
      

      同样,对于您的情况,ssh 有一个 SSH_ASKPASS 环境变量。

      请注意,对于 ssh/rsync 的无头操作,您可以通过直接设置 ssh 代理(如果它尚未运行)并使用您的 SSH_AUTH_SOCK 变量引用它来完全避免来自笔记本的身份验证提示,例如ssh-add 确实如此。 或者您可以通过SSH_ASKPASS 使用不同的程序,它以自定义方式处理身份验证。有关更多详细信息,请参阅How to automate SSH login with password? - Server Fault 之类的问题,但请注意不要危及您的安全,尤其是在尝试自动从一台服务器连接到另一台服务器时。

      【讨论】:

      • 如果我错了,请纠正我,但ssh-askpass 是一个 gui 程序,不是吗?好吧,如果你是在台式机上运行,​​那么如果 ipython/jupyter 在无头服务器上运行就不太方便了。
      • @drevicko 我添加了一些关于无头操作的注释。还有很多其他关于从服务器使用 ssh 和 rsync 的资源,但要注意安全风险并寻求经过充分审查的建议。