Execute commands inside another process? - ruby

I want to be able to start a process and send input to it immediately.
Take Bash as an example.
The following code will enter another Bash process and then print "Hello World!" on the screen after I have terminated the process with "exit"
bash
echo "Hello World!"
Is there a way to enter bash and then print "Hello World!" INSIDE that process?
I'm using Ruby and Bash on Ubuntu.
UPDATE: This question was not intended to be Bash specific. Bash was just an example. It would be better if someone could post an answer that handles all other binaries.

You may be looking for the expect tool.

bash -c 'echo "Hello World!"'
You can also try writing bash script and invoking it:
bash ./myscript
or put #!/bin/bash as the first line in a text file and it will be invoked using bash like any other executable:
./myscript
Update0
Bash is an interpreter. There are many other interpreters, I'd highly recommend you take a look at Python, you can send instructions to be interpreted to these programs easily enough.
You might also be referring to the Unix IO-model, in which case you may want to ask a question relating to the use of piping with stdin and stdout.

%x(some external bash commands)
`ls -1`

Related

How can I suppress output of a bash script from within the script itself?

I have a script that connects to an FTP server and while doing so prints out a load of junk.
Is there a way to 'mute' the ouput of the script, similar to windows #echoff? I saw on another question very similar to mine, not the same though that you could use scriptname >/dev/null. When I put this in my program, obviously replacing scriptname with the name of the script, I got a command not found error message.
Does anyone have any idea why this might be happening.
If you mean you want to redirect all output to /dev/null from within the script, rather than when you execute the script, you can do this:
#!/bin/bash
echo Hi
and run that, like this
./script
then do this
#!/bin/bash
exec 1> /dev/null
echo Hi
and run it again exactly the same way, and see that the output is discarded.
You wouldn't put that in your program, but rather, would use it when calling your program. On the command line:
$ scriptname >/dev/null

SBCL: running from bash and exiting back to bash

I'm new to SBCL and I'm trying to run Lisp scripts stored in text files from a bash terminal.
This is what I write at the beginning of the file as referenced at
http://www.sbcl.org/manual/#Running-from-Shell
#!/usr/local/bin/sbcl --script
(write-line "Hello, World!")
This is the way how I run it from bash terminal:
$ ./hello.lisp
Hello, World!
The problem is that the script terminates back to bash after its execution. I would like the script to not to exit back to bash, but to keep sbcl interpreter running (to be able to use predefined functions for the purposes of testing). Is there a simple way to do so?
Use --eval or -e option.
sbcl --eval '(write-line "Hello, World!")', it'll eval your code and keep you inside REPL.

Bash: What is the effect of "#!/bin/sh" in a bash script with curl

I make a complex and long line command to successful login in a site. If I execute it in Console it work. But if I copy and paste the same line in a bash script it not work.
I tried a lot of thing, but accidentally discovery that if I NOT use the line
#!/bin/sh
it work! Why this happens in my mac OSX Lion? What this config line do in a bash script?
A bash script that is run via /bin/sh runs in sh compatibility mode, which means that many bash-specific features (herestrings, process substitution, etc.) will not work.
sh-4.2$ cat < <(echo 123)
sh: syntax error near unexpected token `<'
If you want to be able to use full bash syntax, use #!/bin/bash as your shebang line.
"#!/bin/sh" is a common idiom to insure that the correct interpreter is used to run the script. Here, "sh" is the "Bourne Shell". A good, standard "least common denominator" for shell scripts.
In your case, however, "#!/bin/sh" seems to be the wrong interpreter.
Here's a bit more info:
http://www.unix.com/answers-frequently-asked-questions/7077-what-does-usr-bin-ksh-mean.html
Originally, we only had one shell on unix. When you asked to run a
command, the shell would attempt to invoke one of the exec() system
calls on it. It the command was an executable, the exec would succeed
and the command would run. If the exec() failed, the shell would not
give up, instead it would try to interpet the command file as if it
were a shell script.
Then unix got more shells and the situation became confused. Most
folks would write scripts in one shell and type commands in another.
And each shell had differing rules for feeding scripts to an
interpreter.
This is when the "#! /" trick was invented. The idea was to let the
kernel's exec() system calls succeed with shell scripts. When the
kernel tries to exec() a file, it looks at the first 4 bytes which
represent an integer called a magic number. This tells the kernel if
it should try to run the file or not. So "#! /" was added to magic
numbers that the kernel knows and it was extended to actually be able
to run shell scripts by itself. But some people could not type "#! /",
they kept leaving the space out. So the kernel was exended a bit again
to allow "#!/" to work as a special 3 byte magic number.
So #! /usr/bin/ksh and
#!/usr/bin/ksh now mean the same thing. I always use the former since at least some kernels might still exist that don't understand the
latter.
And note that the first line is a signal to the kernel, and not to the
shell. What happens now is that when shells try to run scripts via
exec() they just succeed. And we never stumble on their various
fallback schemes.
The very first line of the script can be used to select which script interpreter to use.
With
#!/bin/bash
You are telling the shell to invoke /bin/bash interpreter to execute your script.
Assure that there are not spaces or empty lines before #!/bin/bash or it will not work.

bash script: started with $! instead of #! and got mysterious behavior. What happened?

I accidentally started a bash script with $! instead of #! and got some very weird behavior. I'm trying to figure out what happened.
If you try this script:
$!/bin/bash
echo Hello world!
you will get the following behavior:
$ chmod +x hello
$ ./hello
[nothing happens, get prompt back]
$ exit
exit
Hello world!
$
So it looks like this happened:
A new bash shell spawned.
Upon exit, the rest of the script executed.
What's up? How is anything at all happening? Without #!, how does the shell know to use bash to interpret the script?
Obviously this is a "satisfy my curiosity" rather than "solve my problem" question. Googling does not yield much, probably because #! and $! in queries don't make the Google-bot happy.
$something is a parameter ("variable") expansion, but $! in particular returns a value that isn't set in your script, so it expands as a zero length string.
Therefore your script is, you are correct, the equivalent of:
/bin/bash
echo Hello world!
The shebang magic number is an old feature of Unix, but the shell is even older. A text file with the execute bit set that the kernel cannot exec (because it's not actually compiled) is executed by a subshell. That is, the shell deliberately runs another shell and passes the pathname as the parameter. This is how commands written as shell scripts were executed before shebang was invented, and it's still there in the code.
dollar-bang gets the PID of the last backgrounded process.
http://tldp.org/LDP/abs/html/internalvariables.html (Search for '$!')
Expanding a bit on #DigitalRoss's answer:.
An executable script with no #! on the first line is executed by /bin/sh -- even if you execute it from bash (or tcsh). This isn't shell functionality, it's in the kernel.
So when you executed your script, it was executed by /bin/sh (which means, on most systems, that it won't be able to use bash-specific features), $! expanded to nothing (because that shell hasn't launched any background processes), and the first line invokes an interactive /bin/bash shell. Then you exit from that interactive shell, and your script execute the echo Hello world! line and terminates, putting you back in your original shell.
For example, if you change echo Hello world! to echo $BASH_VERSION, you'll find that it doesn't print anything -- and if you type history from the invoked interactive bash shell, it won't show anything.

Can a script be used as an interpreter by the #! hashbang line?

I'm trying to write a bash script which will behave as a basic interpreter, but it doesn't seem to work: The custom interpreter doesn't appear to be invoked. What am I doing wrong?
Here's a simple setup illustrating the problem:
/bin/interpreter: [owned by root; executable]
#!/bin/bash
echo "I am an interpreter running " $1
/Users/zeph/script is owned by me, and is executable:
#!/bin/interpreter
Here are some commands for the custom interpreter.
From what I understand about the mechanics of hashbangs, the script should be executable as follows:
$ ./script
I am an interpreter running ./script
But this doesn't work. Instead the following happens:
$ ./script
./script: line 3: Here: command not found
...It appears that /bin/bash is trying to interpret the contents of ./script. What am I doing wrong?
Note: Although it appears that /bin/interpreter never invoked, I do get an error if it doesn't exist:
$ ./script
-bash: ./script: /bin/interpreter: bad interpreter: No such file or directory
(Second note: If it makes any difference, I'm doing this on MacOS X).
To make this work you could add the interpreter's interpreter (i.e. bash) to the shebang:
#!/bin/bash /bin/interpreter
Here are some commands for the custom interpreter.
bash will then run your interpreter with the script path in $1 as expected.
You can't use a script directly as a #! interpreter, but you can run the script indirectly via the env command using:
#!/usr/bin/env /bin/interpreter
/usr/bin/env is itself a binary, so is a valid interpreter for #!; and /bin/interpreter can be anything you like (a script of any variety, or binary) without having to put knowledge of its own interpreter into the calling script.
Read the execve man page for your system. It dictates how scripts are launched, and it should specify that the interpreter in a hash-bang line is a binary executable.
I asked a similar question in comp.unix.shell that raised some pertinent information.
There was a second branch of the same thread that carried the idea further.
The most general unix solution is to have the shebang point to a binary executable. But that executable program could be as simple as a single call to execl(). Both threads lead to example C source for a program called gscmd, which is little more than a wrapper to execv("gs",...).

Resources