Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

bash trickery using --init-file

Tags:

bash

I have a bash-script (let's call it /usr/bin/bosh) using the following she-bang line:

#!/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?

I tried writing a script (let's call it /usr/bin/foo) using the she-bang line

#!/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/foo gets executed, but /usr/bin/bosh is not source before that.

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

#!/bin/bash
. /usr/bin/bosh
. "$1"

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.

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?

like image 600
falstro Avatar asked Oct 14 '22 02:10

falstro


1 Answers

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.

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.

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.

Everything you ever wanted to know about #! here: http://www.in-ulm.de/~mascheck/various/shebang/

EDIT: If your kernel really does support chained scripts, then a work-around for /usr/bin/bosh might be something like:

#!/bin/bash
if [ ! $PS1 ]; then
   exec /bin/bash --init-file "$0" -i "$@"
fi
... rest of bosh init file ...

An exec seems to be unavoidable to get this to work the way you want it to.

like image 199
Steve Baker Avatar answered Oct 21 '22 08:10

Steve Baker