Inbash
你可以使用exec -a
and inzsh
你也可以选择ARGV0
使用某个第零个参数来执行一个程序,但是还有一种 POSIX 方法可以这样做吗?
按照建议在这一评论中您可以创建一个(临时)符号链接来实现此目的,但这样我就无法将新的第零个参数值设置为真正的任意值,例如具有特定绝对路径的命令。那么还有其他解决办法吗?
答案1
不,除了编译 C 程序之外,没有 POSIX 方法可以做到这一点。作为一种快速而肮脏的方法:
$ echo 'int main(int c,char*v[]){
execvp(v[1],&v[2]);perror(v[1]);return 127;}'>r.c && make r
$ ./r ps zzz -f
UID PID PPID C STIME TTY TIME CMD
chazelas 7412 7411 0 10:44 pts/4 00:00:00 /bin/zsh
chazelas 21187 7412 0 22:33 pts/4 00:00:00 zzz -f
exec -a
支持ksh93
, bash
, zsh
, busybox ash
(自版本 1.27.0 起), yash
, mksh
(从 r50e 版本开始), 这希利·伯恩外壳(自 2015 年 8 月起)因此是贝壳中应用最广泛的。
也许最可移植的是采用perl
比 C 编译器更可用的编译器。
$ perl -e 'exec {shift} @ARGV' ps zzz -f
UID PID PPID C STIME TTY TIME CMD
chazelas 7554 7411 0 10:58 pts/12 00:00:00 /bin/zsh
chazelas 7630 7554 0 11:02 pts/12 00:00:00 zzz -f
答案2
为了完整起见,这里有一些人们拥有的用于执行此操作的 C 和 C++ 程序已经编译。
根据您指出的评论,您要求“一种 POSIX 方式”执行此操作的明显动机是了解如何使用 Debian Almquist shell、MirBSD Korn shell(版本 R50e 之前的版本)等 shell 实现相同的目标)、符合 Debian POSIX 标准的普通 shell,以及其他没有像 Bourne Again 和 Z shell 那样设置第 0 个参数的扩展的 shell。 ('93 Korn shell 和从版本 R50e 开始的 MirBSD Korn shell,支持-a
其内置exec
命令的选项。)
执行
洛朗·贝尔科特execline
附带一个exec
命令。因此,要复制 M. Chazelas 的示例,需要一个execline
脚本,例如
#!/command/execlineb -P 执行-a zzz ps -f
exec
当然,Bercot是一个普通的外部命令。因此,人们可以从 Debian Almquist Shell 脚本中运行它。要覆盖当前的 shell 程序,可以使用 shellexec
来覆盖 Bercot exec
,这反过来会设置第 0 个参数并覆盖目标程序:
exec /command/exec -a "$argv0" Printer.sh
开胃菜
小吃工具集包括一个exec
命令。为了复制 M. Chazelas 的示例,我们需要一个nosh
脚本,例如
#!/bin/nosh 执行-a zzz ps -f
虽然是nosh
内置的,但是这exec
是还可作为普通外部命令访问。因此,人们可以从 Debian Almquist Shell 脚本中运行它。要覆盖当前的 shell 程序,可以使用 shellexec
与 nosh 工具集的覆盖exec
,这又会设置第 0 个参数并与目标程序覆盖:
exec /usr/local/bin/exec -a "$argv0" Printer.sh
罪犯
韦恩·马歇尔的罪犯包括一个runargv0
命令。这是一个普通的外部命令。因此,人们可以从 Debian Almquist Shell 脚本中运行它。要覆盖当前的 shell 程序,可以使用 shellexec
与 perp 工具集进行覆盖runargv0
,这又会设置第 0 个参数并与目标程序覆盖:
执行 runargv0 Printer.sh "$argv0"
运行
格里特·佩普的鲁尼特包括一个chpst
命令。这是一个普通的外部命令。因此,人们可以从 Debian Almquist Shell 脚本中运行它。要覆盖当前的 shell 程序,可以使用 shellexec
与 runit 进行覆盖chpst
,这反过来会设置第 0 个参数并与目标程序覆盖:
执行 chpst -b "$argv0" Printer.sh
ucspi TCP协议
Daniel J. Bernstein 的 ucspi-tcp包括一个argv0
命令。 (argv0
也可用于DJBwares.) 这是一个普通的外部命令。因此,人们可以从 Debian Almquist Shell 脚本中运行它。要覆盖当前的 shell 程序,可以使用 shellexec
与 ucspi-tcp 进行覆盖argv0
,这又会设置第 0 个参数并与目标程序覆盖:
执行 argv0 打印机.sh "$argv0"