I have a fortran code (wrote by somebody else - cannot change it...) that takes an input parameter file, executes it, then has an interactive prompt. This is how it works:
[user#host] ./mycode
Welcome; what is the file name? _
Once you give it the param file and hit enter, the program executes it and prompts options:
OPTIONS a=add something
u=undo
o=overplot
q=quit
You then interact with the code, and quit. The problem I have is that every time I quit the program and have to start over, I have to keep re-typing the param file name (which is a pain for long names). I would like to write a simple shell-script that would do:
./mycode_auto param_file
Then it would execute the param_file and give the prompt with options. My first naive attempt, which I knew it was missing something:
#!/bin/bash
./mycode << EOF
$1
EOF
It opens mycode, executes the param file, but breaks right after, and I get:
Fortran runtime error: End of file
I can actually understand what it happening, but don't know a way around it. Any ideas?
Thanks!
If you can not modify the fortran program, I believe your only solution will be to use expect. Have a look at the following script :
#!/usr/bin/expect -f
#we store the content of our 1st argument
set file_path [lindex $argv 0]
#process we need to interract with
spawn ./mycode
#if we encounter this message ...
expect "Welcome; what is the file name?" {
#... we send it our first argument
send "$file_path\r"
}
#we resume normal interaction with our script
interact
Simply call it like that : script.expect "/path/to/file", assuming the expect script and mycode are in the same folder.
Related
So, I have a problem. I have downloaded a program from the web. And it's a command line app. I have written a code, which generated some n-k commands to the app. I have written them into an output file. I can write an app in Python, but it freezes on some of the commands. I have tested them manually and seems like there are two issues:
Commands must be run one-by-one;
Some of the commands give an output like bla-bla-bla, this thing is not written into an output file. So, if I run a command ./app -p /file1 -o /file2 -s -a smth- > /fileOutput.txt The fileOutput.txt is empty, though in the terminal, there's is this bla-bla-bla message, stating, that something is wrong. If the command gives bla-bla-bla the app may freeze for a while.
Here is what I want to do:
CD into folder, the containing app;
For command in fileWithCommands perform command and start the next, only when the previous finishes;
If the command gives message, containing bla-bla-bla (cause it may look like file1 bla-bla-bla), write the command and this strange output into file badOutputs.txt.
Have never done applescript before. However, this's what I've done so far:
set theFile to "/Users/MeUser/Desktop/firstCommand"
set fileHandle to open for access theFile
set arrayCommand to paragraphs of (read fileHandle)
#I have found the previous code here: http://alvinalexander.com/mac-os-x/applescript-read-file-into-list-array-examples
close access fileHandle
tell application "Terminal"
activate
do script "cd /Users/MeUser/Desktop/anApp/"
repeat with command in arrayCommand
do script command
end repeat
end tell
Though there's a problem, if in one window the commands make up a huge queue. Without window 1 cd and the command are in different windows. And I am still unable to save the output.
UPDATE
Did with accordance to #Mark Setchell's recommendations. So now I have such code:
set theFile to "/Users/meUser/Desktop/firstCommand"
set fileHandle to open for access theFile
set arrayCommand to paragraphs of (read fileHandle)
close access fileHandle
repeat with command in arrayCommand
do shell script "cd /Users/meUser/Desktop/App/; " & command
end repeat
To the command I have added the following:
2>&1 /Users/meUser/Desktop/errorOut.txt
However, the apple script says that a mistake of the app is the mistake of the script. I.e.: file corrupted, app fails. I want it to write into error file where has it failed and move to the next command, while the script just fails.
Maybe not a complete solution, but more than a comment and easier to format this way...
First Issue
Your command-line app which writes on the Terminal may be writing to stderr rather than stdout. Try redirecting stderr to the same place as stdout by using
./app -p ... > /FileOutput.txt 2>&1
Second Issue
You cannot do:
do shell script cd somewhere
do shell script do_something
because each do shell script will execute in a separate, unrelated process. So your first process will start - in the default directory like all processes - and correctly change directory and then exit. Then your second process will start - in the default directory like all processes - and try to run your command. Rather than that, you can do this:
do shell script "cd somewhere; do_something"
which starts a single process which changes directory and then runs your command line program there.
Issue Three
Why do you want to send your commands to Terminal anyway? Does the user need to see something in Terminal - seems unlikely because you want to capture the output, don't you? Can't you just run your commands using do shell script?
Issue Four
If you want to keep your normal output separate from your error output, you can do:
./app ... params ... > OutputFile.txt 2> errors.txt
Suggestion 1
You can retain all the errors from all the scripts and accumulate them in a single file like this:
./app .. params .. >> results.txt 2>&1
That may enable you to deal with errors separately later.
Suggestion 2
You can capture the output of your shell script into an Applescript variable, say ScriptOutput, like this, then you can parse it:
set ScriptOutput to do shell script "..."
Suggestion 3
If errors caused by your script are stopping your loop, you can enclose them in a try block like this so they are handled and everything continues:
try
do shell script "..."
on error errMsg
display dialog "ERROR: " & errMsg
end try
I wrote a Ruby script like the following example. The basic functionality is the same:
# get input from the user
input = gets.chomp
# do awesome stuf with this input and print the response
puts do_awesome_stuff(input)
The problem is when I run the script it prints the solution I want, but the console window closes right after. I want the console to keep open.
I'm currently on windows, but the solution should be working on every system.
One way is to run the ruby script with a .bat file and pause it, like so:
ruby script.rb
PAUSE
I hope there is a way without the additional .bat file. Does Ruby has a function like PASUE integrated?
It seems like you double click the ruby script file.
Instead issue the following command in cmd shell.
ruby filename.rb
If you don't want that, you can add gets to the end of the script.
# get input from the user
input = gets.chomp
# do awesome stuf with this input and print the response
puts do_awesome_stuff(input)
gets # <----
But this is not recommended because .. if you run the command in cmd shell or terminal you should type extra Enter to return to the shell.
Use the -r options of irb.
irb -r ./filename.rb
Hi. I'm new to the shell and am working on my first kludged together script. I've read all over the intertube and SO and there are many, MANY places where disown, nohup, & and return are explained but something isn't working for me.
I want a simpler timer. The script asks for user input for the hours, mins., etc., then:
echo "No problem, see you then…"
sleep $[a*3600+b*60+c]
At this point (either on the first or second lines, not sure) I want the script OR the specific command in the script to become a background process. Maybe a daemon? So that the timer will still go off on schedule even if
that terminal window is shut
the terminal app is quit completely
the computer is put to sleep (I realize I probably need some different code still to wake the mac itself)
Also after the "No problem" line I want a return command so that the existing shell window is still useful in the meantime.
The terminal-notifier command (the timer wakeup) is getting called immediately under certain usage of the above (I can't remember which right now), then a second notification at the right time. Using the return command anywhere basically seems to quit the script.
One thing I'm not clear on is whether/how disown, nohup, etc. are applicable to a command process vs. a script process, i.e., will any of them work properly on only a command inside a script (and if not, how to initialize a script as a background process that still asks for input).
Maybe I should use some alternative to sleep?
It isn't necessary to use a separate script or have the script run itself in order to get part of it to run in the background.
A much simpler way is to place the portions that you want to be backgrounded (the sleep and following command) inside of parentheses, and put an ampersand after them.
So the end of the script would look like:
(
sleep $time
# Do whatever
)&
This will cause that portion of the code to be run inside a subshell which is placed into the background, since there's no code after that the first shell will immediately exit returning control to your interactive shell.
When your script is run, it is actually run by starting a new shell to execute it. In order for you to get your script into the background, you would need to send that shell into the background, which you can't do because you would need to communicate with its parent shell.
What you can do is have your script call itself with a special argument to indicate that it should do the work:
#! /bin/zsh
if [ "$1" != '--run' ] ; then
echo sending to background
$0 --run $# &
exit
fi
sleep 1
echo backgrounded $#
This script first checks to see if its first argument is --run. If it is not, then it calls itself ($0) with that argument and all other arguments it received ($#) in the background, and exits. You can use a similar method, performing the test when you want to enter the background, and possibly sending the data you will need instead of every argument. For example, to send just the number of seconds:
$0 --run $[a*3600+b*60+c] &
I am seeing odd behaviour when I open a file in append mode ('a+') under Windows 7 using Python.
I was wondering whether the behaviour is in fact incorrect or I am misunderstanding how to use the following code:
log_file= open(log_file_path, "a+")
return_code = subprocess.call(["make", target], stdout=log_file, stderr=subprocess.STDOUT)
log_file.close()
The above code lines does not properly append to the file. In fact on subsequent runs it won't even modify the file.
I tested it out using the Python Shell as well.
Once the file has been opened for the first time, making multiple subprocess calls will append properly to the file, however once the file has been closed and reopened it will never append again.
Anyone have any clues?
Thanks
To further simply the problem Here is another set of steps that will fail:
log_file=open("temp.txt", "a+")
log_file.write("THIS IS A TEST")
log_file.close()
log_file=open("temp.txt", "a+")
subprocess.call(["echo", "test"], stdout=log_file, stderr=subprocess.STDOUT, shell=True)
log_file.close()
If you open the file temp.txt here is what I see:
testS A MUTHER F** TEST
It looks like your problem is in the use of shell=True. From Python documentation for POpen:
On Unix, with shell=True: If args is a string, it specifies the
command string to execute through the shell. This means that the
string must be formatted exactly as it would be when typed at the
shell prompt. This includes, for example, quoting or backslash
escaping filenames with spaces in them. If args is a sequence, the
first item specifies the command string, and any additional items will
be treated as additional arguments to the shell itself.
So it looks like "echo" is the command, and "test" gets sent as an argument to the shell, instead of to "echo".
So changing your subprocess call to either:
subprocess.call("echo test", stdout=log_file, stderr=subprocess.STDOUT, shell=True)
or:
subprocess.call(["echo", "test"], stdout=log_file, stderr=subprocess.STDOUT)
Fixes the problem, at least in my testing.
see http://mail.python.org/pipermail/python-list/2009-October/1221841.html
briefly: opening a file in append mode leaves the file ptr in an implementation-dependent state. seek to the end to get the same results on windows as on linux.
My $SHELL is tcsh. I want to run a C shell script that will call a program many times with some arguments changed each time. The program I need to call is in Fortran. I do not want to edit it. The program only takes arguments once it is executed, but not on the command line. Upon calling the program in the script, the program takes control (this is where I am stuck currently, I can never get out because the script will not execute anything until after the program process stops). At this point I need to pass it some variables, then after several iterations I will need to Ctrl+C out of the program and continue with the script.
How can this be done?
To add to what #Toybuilder said, you can use a "here document". I.e. your script could have
./myfortranprogram << EOF
first line of input
second line of input
EOF
Everything between the "<<EOF" and the "EOF" will be fed to the program's standard input (does Fortran still use "read (5,*)" to read from standard input?)
And because I think #ephemient's comment deserves to be in the answer:
Some more tips: <<'EOF' prevents
interpolation in the here-doc body;
<<-EOF removes all leading tabs (so
you can indent the here-doc to match
its surroundings), and EOF can be
replaced by any token. An empty token
(<<"") indicates a here-doc that stops
at the first empty line.
I'm not sure how portable those ones are, or if they're just tcsh extensions - I've only used the <<EOF type "here document" myself.
What you want to use is Expect.
Uhm, can you feed your Fortran code with a redirection? You can create a temporary file with your inputs, and then pipe it in with the stdin redirect (<).
This is a job for the unix program expect, which can nicely and easily interactively command programs and respond to their prompts.
I was sent here after being told my question was close to being a duplicate of this one.
FWIW, I had a similar problem with a csh C shell script.
This bit of code was allowing the custom_command to execute without getting ANY input arguments:
foreach f ($forecastTimes)
custom_command << EOF
arg1=x$f;2
arg2=ya
arg3=z,z$f
run
exit
EOF
end
It didn't work the first time I tried it, but after I backspaced out all of the white space in that section of the code I removed the space between the "<<" and the "EOF". I also backspaced the closing "EOF" all the way to the left margin. After that it worked:
foreach f ($forecastTimes)
custom_command <<EOF
arg1=x$f;2
arg2=ya
arg3=z,z$f
run
exit
EOF
end
Not a tcsh user, but if the program runs then reads in commands via stdin then you can use shell redirection < to feed it the required commands. If you run it in the background with & you will not block when it is executed. Then you can sleep for a bit, then use whatever tools you have (ps, grep, awk, etc) to discover the program's PID, then use kill to send it SIGTERM which is the same as doing a Ctrl-C.