跳转到主要内容

在本地运行命令和操作文件

项目描述

在本地运行echo

import spur

shell = spur.LocalShell()
result = shell.run(["echo", "-n", "hello"])
print(result.output) # prints hello

通过SSH执行相同的命令使用相同的接口 - 唯一的区别是shell的创建方式

import spur

shell = spur.SshShell(hostname="localhost", username="bob", password="password1")
with shell:
    result = shell.run(["echo", "-n", "hello"])
print(result.output) # prints hello

安装

$ pip install spur

Shell构造函数

LocalShell

不接受任何参数

spur.LocalShell()

SshShell

需要一个主机名。根据需要,还需要一些用户名、密码和私钥的组合来验证

# Use a password
spur.SshShell(
    hostname="localhost",
    username="bob",
    password="password1"
)
# Use a private key
spur.SshShell(
    hostname="localhost",
    username="bob",
    private_key_file="path/to/private.key"
)
# Use a port other than 22
spur.SshShell(
    hostname="localhost",
    port=50022,
    username="bob",
    password="password1"
)

可选参数

  • connect_timeout - 建立SSH连接的秒数超时。默认为60秒(一分钟)。

  • missing_host_key - 默认情况下,当主机密钥缺失时将引发错误。可以使用以下值之一来更改主机密钥缺失时的行为

    • spur.ssh.MissingHostKey.raise_error - 引发错误

    • spur.ssh.MissingHostKey.warn - 接受主机密钥并记录警告

    • spur.ssh.MissingHostKey.accept - 接受主机密钥

  • shell_type - 主机使用的shell类型。默认为 spur.ssh.ShellTypes.sh,这应该适用于大多数Linux发行版。如果主机使用不同的shell,例如在嵌入式系统中常见的简单shell,请尝试将 shell_type 改为更合适的值,例如 spur.ssh.ShellTypes.minimal。目前支持以下shell类型

    • spur.ssh.ShellTypes.sh – Bourne shell。支持所有功能。

    • spur.ssh.ShellTypes.minimal – 最小化shell。不支持几个功能。

      • 不存在的命令不会引发 spur.NoSuchCommandError

      • 除非设置为它们的默认值,否则不支持 spawnrun 的以下参数:cwdupdate_envstore_pid

  • look_for_private_keys – 默认情况下,Spur将在 ~/.ssh/ 中搜索可发现的私钥文件。设置为 False 以禁用此行为。

  • load_system_host_keys – 默认情况下,Spur将尝试从OpenSSH使用的用户已知主机文件中读取主机密钥,如果文件无法读取,则不会引发异常。设置为 False 以禁用此行为。

  • sock – 用于与目标主机通信的开放套接字或类似套接字的对象。例如

    sock=paramiko.proxy.ProxyCommand(
        "ssh -q -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null"
        "bob@proxy.example.com nc -q0 target.example.com 22"
    )

    类似套接字对象的示例包括

Shell接口

run(command, cwd, update_env, store_pid, allow_error, stdout, stderr, encoding)

运行一个命令并等待其完成。命令预期为字符串列表。返回 ExecutionResult 的实例。

result = shell.run(["echo", "-n", "hello"])
print(result.output) # prints hello

请注意,参数未进行任何shell展开。例如,shell.run(["echo", "$PATH"]) 将打印字面字符串 $PATH 而不是环境变量 $PATH 的值。

如果尝试执行不存在的命令,则引发 spur.NoSuchCommandError

可选参数

  • cwd – 在执行命令之前将当前目录更改为此值。

  • update_env – 一个包含要在运行命令之前设置的环境变量的 dict。如果存在具有相同名称的环境变量,则将其覆盖。否则,保持不变。

  • store_pid – 如果在调用 spawn 时设置为 True,则将创建进程的进程ID存储为返回的进程对象的属性 pid。在调用 run 时没有效果。

  • allow_error – 默认为 False。如果为 False,则如果命令的返回码不是0,将引发异常。如果为 True,则无论返回码如何,都返回结果。

  • stdout – 如果不是 None,则在命令执行期间打印到标准输出的任何内容也将使用 stdout.write 写入到 stdout

  • stderr – 如果不是 None,则在命令执行期间打印到标准错误的任何内容也将使用 stderr.write 写入到 stderr

  • 编码 – 如果设置,将用于解码任何输出。默认情况下,任何输出都视为原始字节。如果设置,则在写入传递的 stdoutstderr 参数(如果已设置)以及设置结果输出属性之前,将解码原始字节。

shell.run(*args, **kwargs) 应该与 shell.spawn(*args, **kwargs).wait_for_result() 类似。

spawn(command, cwd, update_env, store_pid, allow_error, stdout, stderr, encoding)

行为与 run 相同,但 spawn 会立即返回表示正在运行进程的对象。

如果尝试执行不存在的命令,则引发 spur.NoSuchCommandError

open(path, mode=”r”)

path 处打开文件。返回一个文件对象。

默认情况下,文件以文本模式打开。将 “b” 添加到模式将使文件以二进制模式打开。

例如,要使用 SSH 复制二进制文件,假设您已经有一个 SshShell 实例

with ssh_shell.open("/path/to/remote", "rb") as remote_file:
    with open("/path/to/local", "wb") as local_file:
        shutil.copyfileobj(remote_file, local_file)

进程接口

shell.spawn 调用返回。具有以下属性

  • pid – 进程的进程 ID。只有在调用 spawn 时将 store_pid 设置为 True 时才可用。

具有以下方法

  • is_running() – 如果进程仍在运行,则返回 True,否则返回 False

  • stdin_write(value) – 将 value 写入进程的标准输入。

  • wait_for_result() – 等待进程退出,然后返回一个 ExecutionResult 实例。如果返回代码不是零且未使用 allow_error=True 调用 shell.spawn,则将引发 RunProcessError

  • send_signal(signal) – 向进程发送信号 signal。只有在调用 spawn 时将 store_pid 设置为 True 时才可用。

ExecutionResult

ExecutionResult 有以下属性

  • return_code – 命令的返回码

  • output – 包含捕获的 stdout 结果的字符串

  • stderr_output – 包含捕获的 stderr 结果的字符串

它还具有以下方法

  • to_error() – 返回相应的 RunProcessError。如果您想有条件地引发 RunProcessError,这很有用,例如

result = shell.run(["some-command"], allow_error=True)
if result.return_code > 4:
    raise result.to_error()

RunProcessError

RuntimeError 的子类,具有与 ExecutionResult 相同的属性

  • return_code – 命令的返回码

  • output – 包含捕获的 stdout 结果的字符串

  • stderr_output – 包含捕获的 stderr 结果的字符串

NoSuchCommandError

NoSuchCommandError 有以下属性

  • command – 找不到的命令

API 稳定性

使用 语义版本控制 的术语,如果 spur 的版本是 X.Y.Z,则 X 是主版本,Y 是次版本,Z 是修补版本。

当主版本为 0 时,增加修补版本表示向后兼容的更改。例如,如果您正在使用 0.3.1,则可以安全地升级到 0.3.2。

增加次版本表示 API 发生变化。这意味着在使用 spur 的先前次版本的任何代码可能需要更新才能使用当前次版本。

未记录的功能

一些功能尚未文档化,应被视为实验性的。请自行承担使用风险。它们可能不会按预期运行,其行为和接口可能随时更改。

故障排除

当我尝试使用本地主机上的转发端口连接虚拟机时,出现“连接被拒绝”错误

尝试使用"127.0.0.1"而不是"localhost"作为主机名。

尝试通过SSH执行命令时出现“连接被拒绝”错误

尝试使用命令行上的SSH连接到该机器,使用相同的设置。例如,如果您正在使用以下代码:

shell = spur.SshShell(
        hostname="remote",
        port=2222,
        username="bob",
        private_key_file="/home/bob/.ssh/id_rsa"
    )
with shell:
    result = shell.run(["echo", "hello"])

尝试运行

ssh bob@remote -p 2222 -i /home/bob/.ssh/id_rsa

如果ssh命令成功,请确保ssh.SshShell和ssh命令的参数相同。如果ssh.SshShell的任何参数是动态生成的,请尝试将它们硬编码,以确保它们设置为预期的值。

我无法通过SSH启动或运行命令

如果您在通过SSH启动或运行命令时遇到问题,请尝试将shell_type=spur.ssh.ShellTypes.minimal作为参数传递给spur.SshShell。例如

import spur
import spur.ssh

spur.SshShell(
    hostname="localhost",
    username="bob",
    password="password1",
    shell_type=spur.ssh.ShellTypes.minimal,
)

这将对主机shell支持的特性做出最小假设,特别适用于嵌入式系统上发现的简单shell。如果主机shell功能更全但仅与spur.ssh.ShellTypes.minimal兼容,请随时提交问题。

为什么变量和重定向等shell功能不起作用?

命令是直接运行的,而不是通过shell。如果您想使用任何shell功能(如变量和重定向),则需要在这些命令中运行适当的shell。例如

shell.run(["sh", "-c", "echo $PATH"])
shell.run(["sh", "-c", "ls | grep bananas"])

项目详情


下载文件

下载适用于您平台的应用程序。如果您不确定选择哪个,请了解更多关于安装包的信息。

源分发

spur.local-0.3.19.tar.gz (12.2 kB 查看哈希)

上传时间

由以下机构支持

AWS AWS 云计算和安全赞助商 Datadog Datadog 监控 Fastly Fastly CDN Google Google 下载分析 Microsoft Microsoft PSF 赞助商 Pingdom Pingdom 监控 Sentry Sentry 错误日志 StatusPage StatusPage 状态页面