根据man systemd.service
使用前缀的手册@
是这样说的:
如果可执行路径以“@”为前缀,则第二个指定的标记将作为“argv[0]”传递到执行的进程(而不是实际的文件名),后面跟着指定的其他参数。
但是当我使用 bash 脚本或 python 脚本运行服务时,文件名或 argv[0] 不起作用。仅当我使用用 C 语言编写的程序时,这才有效。
在我的服务中,我有:
[Unit]
Description=After service Number: 1
[Service]
Type=oneshot
ExecStart=@/home/edgar/bin/script "after-1-service" "1" "Args from after-service"
[Install]
WantedBy=multi-user.target
当我使用运行此服务时C程序文件名的值为“1后服务”和其他参数(“1”,“来自售后服务的参数”)正确传递为参数[1]和参数[2]分别。
但是当我使用运行服务时Python或者巴什脚本的值“1后服务”没有效果并打印脚本的主文件名,参数“1”和“Args from after-service”被正确传递为参数[1]和参数[2]分别。
对于 python 和 bash 脚本,发生了什么“1后服务”争论?因为如果文件名或 argv[0] 被忽略,我想它应该被传递“1后服务”作为 argv[1] ,其他参数应作为参数[2]和参数[3]
这是我编写的c
用于打印文件名的代码:
printf("Filename: %s\n",argv[0]);
这是我写的代码python
:
print(f"Filename: {sys.argv[0]}")
这是我编写的代码bash
:
echo Filename $0
我已经使用符号链接和文件名更改正确测试了这些脚本,所以我猜这仅适用于 C 程序,或者可能是 systemd(版本 251)的错误。
答案1
这里的问题是 shell 进程的进程与shell 脚本内的argv[0]
进程不同。$0
即使正常启动脚本也可以看到这一点:
$ cat argv0.sh
#!/bin/sh
echo "Filename $0"
$ sh ./argv0.sh
Filename ./argv0.sh
shell 会调用诸如execve("/bin/sh", ["sh", "./argv0.sh"], [env vars...])
ie argv[0]
gets set to之类的内容sh
。但是,脚本中的$0
名称是脚本运行后,手册页显示:
0
扩展为 shell 或 shell 脚本的名称。这是在 shell 初始化时设置的。如果使用命令文件调用 bash,$0
则设置为该文件的名称。”
就该功能而言,名称是什么并不重要口译员被设定为。
我认为这个问题原则上与 Python 类似,例如手册说:
sys.argv
传递给 Python 脚本的命令行参数列表。argv[0]
是脚本名称(无论是否是完整路径名,都取决于操作系统)。
然而,Python 3.10 也有sys.orig_argv
它看起来可能是你正在寻找的:
sys.orig_argv
传递给 Python 可执行文件的原始命令行参数列表。
如果 shell 以 启动sh -c "code..." arg0 arg1 ...
,则代码后的第一个参数将被分配给$0
,因此您可以使用它并运行如下所示的代码:
$ sh -c '. ./argv0.sh' foobar
Filename foobar
用于. ./argv0.sh
在同一个 shell 中运行脚本,以便它看到相同的内容$0
等。