如何从非Shell应用程序调用Shell命令?

超级欧派课程 2024-03-06 15:05:15

要从非Shell应用程序调用Shell命令,可以使用Shell的-c选项来运行一小段脚本。这个选项的唯一目的是执行脚本。下面是一个示例:

sh -c 'echo "Hi! This is a short script."'

然而,如果没有一种传递数据的方法,这种方法通常是无用的。最佳的传递数据给Shell的方法是将数据作为位置参数传递。下面是一个示例:

sh -c 'echo "Hi! This short script was run with the arguments: $@"' -- "foo" "bar"

需要注意的是,在实际的位置参数之前需要使用--符号。传递给Shell进程的第一个参数(不是-c​选项的参数)将存储在$0​中。位置参数从$1​开始,因此我们在$0​中放置了一个小占位符。这个占位符可以是任何你喜欢的内容,在示例中我们使用了通用的--​符号。

这种技术在Shell脚本中经常使用,特别是当尝试让非Shell命令行实用程序执行一些Bash代码时。例如,在使用find​命令时,可以这样调用Shell命令:

find /foo -name '*.bar' -exec bash -c 'mv "$1" "${1%.bar}.jpg"' -- {} \;

在这个例子中,我们使用find​命令对每个找到的*.bar​文件运行了一个Bash命令,将文件作为第一个位置参数传递给Bash进程。然后,在Bash进程中对文件的第一个位置参数进行了一些参数展开,最后运行了mv​命令,将文件的扩展名从.bar​重命名为.jpg​。

另外,如果您的非Shell应用程序允许您设置环境变量,您可以设置环境变量,然后在Shell中使用相同名称的普通变量来读取它们。

类似地,假设一个程序(例如文件管理器)允许您定义一个外部命令,其中一个参数将被附加到该命令的中间位置。在这种情况下,可以使用以下方式:

#!/bin/shsh -c 'command foo "$1" bar' -- "$@"调用Shell函数

只有Shell能够调用Shell函数。因此,下面这种结构是行不通的:

# 这样是不可行的!find . -type f -exec my_bash_function {} +

如果您的Shell函数在一个文件中进行定义,您可以调用一个源自该文件的Shell,并在其中调用该函数:

find . -type f -exec bash -c 'source /my/bash/function; my_bash_function "$@"' _ {} +

Bash还允许通过环境导出函数定义。因此,如果您的函数在当前Shell中定义,可以将其导出,使其对find调用的新Shell可用:

# Bashexport -f my_bash_functionfind . -type f -exec bash -c 'my_bash_function "$@"' _ {} +

这种方法仅适用于Bash,并且并非没有问题。函数代码的最大长度不能超过环境变量的最大大小,这是平台特定的。在环境中导出函数也可能存在安全风险,因为Bash只是扫描环境变量以找到符合Shell函数形式的值,并且无法知道谁导出了函数,或者看起来像函数的值是否确实是函数。通常最好的做法是检索函数定义并将其直接放入代码中,这样也更具可移植性。

以下是一个示例,展示了如何在脚本中检索函数定义并将其直接放入代码中,以实现可移植性:

# Bash/ksh/zshfunction someFunc { # 函数定义 :}bash -s <<EOF$(typeset -f someFunc) # 检索函数定义并将其放入代码中someFunc # 调用函数EOF

当在远程系统上调用Shell函数时,也需要使用类似的技术。如果远程系统上有包含函数定义的文件可用,可以通过在远程系统上导入包含函数定义的文件来实现。如果没有这样的文件可用,唯一可行的方法是要求当前的Shell输出函数定义,并将其通过SSH通道传递给远程Shell:

{ declare -f my_bash_function # 输出函数定义 echo "my_bash_function foo 'bar bar'" # 调用函数} | ssh -T user@host bash

在编写要通过SSH发送的脚本时,必须小心。SSH的工作方式类似于eval,具有相同的注意事项。

如果您觉得文章内容对你有一点帮助可以关注我,我在头条平台会持续分享更多实用的shell技巧和最佳实践,如果想系统的快速学习shell的各种高阶用法和生产环境避坑指南可以看看《shell脚本编程最佳实践》专栏,专栏里有更多的实用小技巧和脚本代码分享。

0 阅读:0

超级欧派课程

简介:感谢大家的关注