Is it possible to read binary in a Ruby file and execute it directly in memory?
For example, I want to do something like this:
x = IO.read('/bin/ls')
execute(x)
I tried system(x) but it returned:
ArgumentError: string contains null byte
I don't think you're going to be able to do that. When an executable starts, the dynamic linker needs to do quite a lot of fixing links up.
The simplest solution is to write the executable to a temporary disk file somewhere, and execute that.
system() and exec() both pass the command string to the OS to have it load and launch an external command, which isn't what you're asking to do.
For instance, this is from the system() documentation:
Executes command... in a subshell.
command... is one of following forms.
commandline:
command line string which is passed to the standard shell
cmdname, arg1, ...:
command name and one or more arguments (no shell)
[cmdname, argv0], arg1, ...:
command name, argv[0] and zero or more arguments (no shell)
Something could probably be written in C, as that is how Ruby is extended. There is lots of information on Google.
Related
I'm a bit confused (no experience with this stuff)
So, I'm supposed to run a terminal command that looks something like this:
./script_name file.txt "1, 2, 5"
So, the command would run a script that would take a file and print out the lines indicated in the string (this is just an example).
I'm just a bit confused how to do that in-line with running the script, like how the command indicates. I understand that I can run the script first, and then get user input for which lines, etc, which file, etc. But how is such a command like above setup and used in the script?
I can include file.txt in the same directory and I assume it can be accessed that way, so it wouldn't be a problem. It's the string that is confusing me. How would that be used and stored prior to running the script first and asking for user input?
I've got a very simple rust program but its not doing quite what I'd expect. Running on Windows, using a powershell prompt, I can do the following to display the path:
echo "%PATH%"
and I have a simple Rust program with:
Command::new("echo")
.arg("%PATH%")
.spawn()
.expect("ls command failed to start");
The command will launch and run, but it outputs:
%PATH%
instead of the path contents, like I'd expect. Other commands which don't use special characters seem to work as expected, so I suspect its related to handling them but I don't see a way in Rust to make the command any more primitive than it already is.
I've tried various formatting but it either fails to run the command or does the same.
I also tried using $env:path, but this always fails to run from Rust with a cannot find the path specified error.
Are there any suggestions for handling this? I could write the contents to a file and run the file instead, but running these types of commands from other languages directly works fine so I think it should work from Rust as well.
Thanks!
Update:
Managed to get the expected results from by using:
let out = Command::new("cmd")
.arg("/C")
.arg("echo %PATH%")
.spawn()
.expect("ls command failed to start");
}
I think the question got interpreted a bit differently, as getting the path was just an example of a larger issue I was seeing. Updating with the above solved my larger issue as well.
As the comment by French says: Spawning the process does not include the Powershell-environment, which would expand %PATH% to it's actual content before launching the process.
You need to get the content of PATH via std::env yourself or lookup the Powershell documentation on how to launch a subprocess inside a powershell-session.
As others have mentioned, it's not the special characters, it's the fact that those special characters are interpreted by powershell before the "echo" program runs at all.
Using https://doc.rust-lang.org/cargo/reference/environment-variables.html as a reference for how to look up environment variables, try something like this:
use std::env;
fn main() {
let cur_path = env::var("PATH").unwrap();
println!("Environment is: {}", cur_path);
}
You can try this here: https://play.rust-lang.org/
You can then feed cur_path into your "Command::new" if you wish. The trick is that powershell substitutes that argument BEFORE launching echo, which you may not have known, whereas when you execute the echo program directly, you have to do that substitution yourself.
I am currently writing a Python script that will pipe some RNA sequences (strings) into a UNIX executable, which, after processing them, will then send the output back into my Python script for further processing. I am doing this with the subprocess module.
However, in order for the executable to run, it must also have some additional arguments provided to it. Using the subprocess.call method, I have been trying to run:
import subprocess
seq= "acgtgagtag"
output= subprocess.Popen(["./DNAanalyzer", seq])
Despite having my environmental variables set properly, the executables running without problem from the command line of the terminal, and the subprocess module functioning normally (e.g. subprocess.Popen(["ls"]) works just fine), the Unix executable prints out the same output:
Failed to open input file acgtgagtag.in
Requesting input manually.
There are a few other Unix executables in this package, and all of them behave the same way. I even tried to create a simple text file containing the sequence and specify it as the input in both the Python script as well as within the command line, but the executables only want manual input.
I have looked through the package's manual, but it does not mention why the executables can ostensibly be only run through the command line. Because I have limited experience with this module (and Python in general), can anybody indicate what the best approach to this problem would be?
The Popen() is actually a constructor for an object – that object being a "sub-shell" that directly runs the executable. But because I didn't set a standard input or output (stdin and stdout), they default to None, meaning that the process's I/O are both closed.
What I should have done is pass subprocess.PIPE to signify to the Popen object that I want to pipe input and output between my program and the process.
Additionally, the environment variables of the script (in the main shell) were not the same as the environment variables of the subshell, and these specific executables needed certain environment variables in order to function (in this case, it was the path to the parameter files in its package). This was done in the following fashion:
import subprocess as sb
seq= "acgtgagtag"
my_env= {BIOPACKAGEPATH: "/Users/Bobmcbobson/Documents/Biopackage/"}
p= sb.Popen(['biopackage/bin/DNAanalyzer'], stdin=sb.PIPE, stdout=sb.PIPE, env=my_env)
strb = (seq + '\n').encode('utf-8')
data = p.communicate(input=strb)
After creating the Popen object, we send it a formatted input string using communicate(). The output can now be read, and further processed in whatever way in the script.
Bash commands are available from an interactive tclsh session. E.g. in a tclsh session you can have
% ls
instead of
$ exec ls
However, you cant have a tcl script which calls bash commands directly (i.e. without exec).
How can I make tclsh to recognize bash commands while interpreting tcl script files, just like it does in an interactive session?
I guess there is some tcl package (or something like that), which is being loaded automatically while launching an interactive session to support direct calls of bash commans. How can I load it manually in tcl script files?
If you want to have specific utilities available in your scripts, write bridging procedures:
proc ls args {
exec {*}[auto_execok ls] {*}$args
}
That will even work (with obvious adaptation) for most shell builtins or on Windows. (To be fair, you usually don't want to use an external ls; the internal glob command usually suffices, sometimes with extra help from some file subcommands.) Some commands need a little more work (e.g., redirecting input so it comes from the terminal, with an extra <#stdin or </dev/tty; that's needed for stty on some platforms) but that works reasonably well.
However, if what you're asking for is to have arbitrary execution of external programs without any extra code to mark that they are external, that's considered to be against the ethos of Tcl. The issue is that it makes the code quite a lot harder to maintain; it's not obvious that you're doing an expensive call-out instead of using something (relatively) cheap that's internal. Putting in the exec in that case isn't that onerous…
What's going on here is that the unknown proc is getting invoked when you type a command like ls, because that's not an existing tcl command, and by default, that command will check that if the command was invoked from an interactive session and from the top-level (not indirectly in a proc body) and it's checking to see if the proc name exists somewhere on the path. You can get something like this by writing your own proc unknown.
For a good start on this, examine the output of
info body unknown
One thing you should know is that ls is not a Bash command. It's a standalone utility. The clue for how tclsh runs such utilities is right there in its name - sh means "shell". So it's the rough equivalent to Bash in that Bash is also a shell. Tcl != tclsh so you have to use exec.
I have a .sh file which i am trying to run using runtime api.
It runs perfectly if .sh file is under main project folder, but I want it to be accessed from outside the project folder.
example: /home/test/test.sh.
When i try to run this I get /home/test/test.sh not found error
Can anyone tell me how to execute .sh file using runtime accessing the file from local system?
is the .sh file chmoded to be executable?
if its not you could either:
chmod +x /home/test/test.sh
or
when you call the script pass it through sh so:
sh /home/test/test.sh
Runtime.exec() is not a command line
One pitfall to cover with Runtime.exec() is mistakenly assuming that exec() accepts any String that your command line (or shell) accepts. Runtime.exec() is much more limited and not cross-platform. This pitfall is caused by users attempting to use the exec() method to accept a single String as a command line would. The confusion may be due to the fact that command is the parameter name for the exec() method. Thus, the programmer incorrectly associates the parameter command with anything that he or she can type on a command line, instead of associating it with a single program and its arguments.