使用 --init-file 的 bash 诡计
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3361095/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
bash trickery using --init-file
提问by falstro
I have a bash-script (let's call it /usr/bin/bosh) using the following she-bang line:
我有一个/usr/bin/bosh使用以下 she-bang 行的 bash 脚本(我们称之为):
#!/bin/bash --init-file
It defines a couple of functions, and generally puts the interactive shell in an environment where the user can control a bunch of stuff that I want. This works pretty well. Now for the interesting part, I'd like to be able to let users use this in-between-layer for writing new scripts, without explicitly havnig to source this one. Is that at all possible?
它定义了几个函数,并且通常将交互式 shell 置于用户可以控制我想要的一堆东西的环境中。这很好用。现在是有趣的部分,我希望能够让用户使用这个中间层来编写新脚本,而无需明确地获取这个脚本。这可能吗?
I tried writing a script (let's call it /usr/bin/foo) using the she-bang line
我尝试/usr/bin/foo使用 she-bang 线编写脚本(我们称之为)
#!/usr/bin/bosh
Which I thought, would be rewritten to execute the command
我认为,将被重写以执行命令
/usr/bin/bosh /usr/bin/foo
which in turn would result in
这反过来会导致
/bin/bash --init-file /usr/bin/bosh /usr/bin/foo
But it doesn't work, /usr/bin/foogets executed, but /usr/bin/boshis not source before that.
但它不起作用,/usr/bin/foo被执行,但/usr/bin/bosh在此之前不是源。
How can I make it source the init file even though the script is not interactive? Or would I have to write a wrapper script for that? I thought of having a script like this
即使脚本不是交互式的,我如何使它成为 init 文件的源?或者我是否必须为此编写一个包装脚本?我想过这样的剧本
#!/bin/bash
. /usr/bin/bosh
. ""
But that wouldn't turn into an interactive shell if I don't specify a script to run, which would be kind of a shame.
但是,如果我不指定要运行的脚本,那将不会变成交互式 shell,这将是一种耻辱。
EDIT
For clarification, what I'm really asking is, how can I make bash source a file (like --init-file) regardless whether it's interactive (before starting the interactive part) or not (before executing the script)? If there's no way, is there any other way to solve my problem perhaps?
编辑
为了澄清起见,我真正要问的是,无论它是交互式的(在开始交互式部分之前)还是不是交互式的(在执行脚本之前),我怎样才能使 bash 源文件成为一个文件(如 --init-file)?如果没有办法,有没有其他方法可以解决我的问题?
采纳答案by Steve Baker
The program specified by the #! cannot be another script I'm afraid at least until linux kernel 2.6.27.9, which allows this feature. If you run strace on foo you'll see that you'd get an ENOEXEC or exec format error, because bosh cannot be executed as a standalone program.
#! 指定的程序 恐怕至少在允许此功能的 linux 内核 2.6.27.9 之前不能是另一个脚本。如果您在 foo 上运行 strace,您将看到您将收到 ENOEXEC 或 exec 格式错误,因为 bosh 不能作为独立程序执行。
What is happening is that instead of /bin/bosh being executed and handed foo as input, your login shell is simply silently falling back to executing foo itself in a sub-shell, which is why it seems to almost work.
正在发生的事情是,不是 /bin/bosh 被执行并将 foo 作为输入传递,您的登录 shell 只是默默地回退到在子 shell 中执行 foo 本身,这就是它似乎几乎可以工作的原因。
A wrapper or C program that launches bash the way you want are probably your only options. Even with an upgrade to your kernel, it will not quite work the way you want I'm afraid.
以您想要的方式启动 bash 的包装器或 C 程序可能是您唯一的选择。即使升级到您的内核,恐怕也不会完全按照您想要的方式工作。
Everything you ever wanted to know about #! here: http://www.in-ulm.de/~mascheck/various/shebang/
你想知道的关于#! 在这里:http: //www.in-ulm.de/~mascheck/various/shebang/
EDIT: If your kernel really does support chained scripts, then a work-around for /usr/bin/boshmight be something like:
编辑:如果您的内核确实支持链式脚本,那么解决方法/usr/bin/bosh可能类似于:
#!/bin/bash
if [ ! $PS1 ]; then
exec /bin/bash --init-file "##代码##" -i "$@"
fi
... rest of bosh init file ...
An exec seems to be unavoidable to get this to work the way you want it to.
执行官似乎不可避免地要让它按照你想要的方式工作。
回答by Adam Outler
A script is not a runtime environment. That may be your problem. The shebang defnies the runtime environment. ie... /bin/java /bin/python /bin/bash /bin/dash. Your script is not an environment. Your "wrapper example" would be appropriate.
脚本不是运行时环境。那可能是你的问题。shebang 定义了运行时环境。即... /bin/java /bin/python /bin/bash /bin/dash. 您的脚本不是环境。您的“包装器示例”是合适的。

