Launching a Perl script without output - perl

I'm making a script (Perl or shell) that launches a second Perl script. The script that it's launching has thousands of lines of output. So basically I want to make a script that launches another script without any output - and if possible run it within a screen session and then exit the script (yet keep the other running in the screen)? How can I do this?

When you launch your script direct output to /dev/null. To make a script run in the background use the & symbol. For example the follow will show nothing in the console and run in the background...
echo hi > /dev/null &

If you want to run in screen, you have to create a screenrc
#!/bin/sh
echo "screen my_perl_program" > /tmp/$$.screenrc
echo "autodetach on" >> /tmp/$$.screenrc
echo "startup_message off" >> /tmp/$$.screenrc
screen -L -dm -S session1 -c /tmp/$$.screenrc
Then you can restore it with screen -S session1

Related

Why is inotifywait not executing the body of the while loop

I had inotifywait working well, and suddenly it has stopped working as I expected. I'm not sure what's happening. My script:
#!/bin/bash
while inotifywait -e modify foo.txt; do
echo we did it
done
echo $?
When I execute it, I get:
Setting up watches.
Watches established.
When I edit foo.txt, I get:
0
And then the script exits.
Why is the while loop exiting given that the exit code is 0?
Why is it never echoing the content of the while loop?
UPDATE
This version does work. However I still don't get what's wrong with the original (given that, I swear, it was working for some time.)
#!/bin/bash
echo helle
while true; do
inotifywait -e modify foo.txt
echo hello
done

setup new database in ubuntu using a script [duplicate]

I have a script where I need to start a command, then pass some additional commands as commands to that command. I tried
su
echo I should be root now:
who am I
exit
echo done.
... but it doesn't work: The su succeeds, but then the command prompt is just staring at me. If I type exit at the prompt, the echo and who am i etc start executing! And the echo done. doesn't get executed at all.
Similarly, I need for this to work over ssh:
ssh remotehost
# this should run under my account on remotehost
su
## this should run as root on remotehost
whoami
exit
## back
exit
# back
How do I solve this?
I am looking for answers which solve this in a general fashion, and which are not specific to su or ssh in particular. The intent is for this question to become a canonical for this particular pattern.
Adding to tripleee's answer:
It is important to remember that the section of the script formatted as a here-document for another shell is executed in a different shell with its own environment (and maybe even on a different machine).
If that block of your script contains parameter expansion, command substitution, and/or arithmetic expansion, then you must use the here-document facility of the shell slightly differently, depending on where you want those expansions to be performed.
1. All expansions must be performed within the scope of the parent shell.
Then the delimiter of the here document must be unquoted.
command <<DELIMITER
...
DELIMITER
Example:
#!/bin/bash
a=0
mylogin=$(whoami)
sudo sh <<END
a=1
mylogin=$(whoami)
echo a=$a
echo mylogin=$mylogin
END
echo a=$a
echo mylogin=$mylogin
Output:
a=0
mylogin=leon
a=0
mylogin=leon
2. All expansions must be performed within the scope of the child shell.
Then the delimiter of the here document must be quoted.
command <<'DELIMITER'
...
DELIMITER
Example:
#!/bin/bash
a=0
mylogin=$(whoami)
sudo sh <<'END'
a=1
mylogin=$(whoami)
echo a=$a
echo mylogin=$mylogin
END
echo a=$a
echo mylogin=$mylogin
Output:
a=1
mylogin=root
a=0
mylogin=leon
3. Some expansions must be performed in the child shell, some - in the parent.
Then the delimiter of the here document must be unquoted and you must escape those expansion expressions that must be performed in the child shell.
Example:
#!/bin/bash
a=0
mylogin=$(whoami)
sudo sh <<END
a=1
mylogin=\$(whoami)
echo a=$a
echo mylogin=\$mylogin
END
echo a=$a
echo mylogin=$mylogin
Output:
a=0
mylogin=root
a=0
mylogin=leon
A shell script is a sequence of commands. The shell will read the script file, and execute those commands one after the other.
In the usual case, there are no surprises here; but a frequent beginner error is assuming that some commands will take over from the shell, and start executing the following commands in the script file instead of the shell which is currently running this script. But that's not how it works.
Basically, scripts work exactly like interactive commands, but how exactly they work needs to be properly understood. Interactively, the shell reads a command (from standard input), runs that command (with input from standard input), and when it's done, it reads another command (from standard input).
Now, when executing a script, standard input is still the terminal (unless you used a redirection) but the commands are read from the script file, not from standard input. (The opposite would be very cumbersome indeed - any read would consume the next line of the script, cat would slurp all the rest of the script, and there would be no way to interact with it!) The script file only contains commands for the shell instance which executes it (though you can of course still use a here document etc to embed inputs as command arguments).
In other words, these "misunderstood" commands (su, ssh, sh, sudo, bash etc) when run alone (without arguments) will start an interactive shell, and in an interactive session, that's obviously fine; but when run from a script, that's very often not what you want.
All of these commands have ways to accept commands by ways other than in an interactive terminal session. Typically, each command supports a way to pass it commands as options or arguments:
su root -c 'who am i'
ssh user#remote uname -a
sh -c 'who am i; echo success'
Many of these commands will also accept commands on standard input:
printf 'uname -a; who am i; uptime' | su
printf 'uname -a; who am i; uptime' | ssh user#remote
printf 'uname -a; who am i; uptime' | sh
which also conveniently allows you to use here documents:
ssh user#remote <<'____HERE'
uname -a
who am i
uptime
____HERE
sh <<'____HERE'
uname -a
who am i
uptime
____HERE
For commands which accept a single command argument, that command can be sh or bash with multiple commands:
sudo sh -c 'uname -a; who am i; uptime'
As an aside, you generally don't need an explicit exit because the command will terminate anyway when it has executed the script (sequence of commands) you passed in for execution.
If you want a generic solution which will work for any kind of program, you can use the expect command.
Extract from the manual page:
Expect is a program that "talks" to other interactive programs according to a script. Following the script, Expect knows what can be expected from a program and what the correct response should be. An interpreted language provides branching and high-level control structures to direct the dialogue. In addition, the user can take control and interact directly when desired, afterward returning control to the script.
Here is a working example using expect:
set timeout 60
spawn sudo su -
expect "*?assword" { send "*secretpassword*\r" }
send_user "I should be root now:"
expect "#" { send "whoami\r" }
expect "#" { send "exit\r" }
send_user "Done.\n"
exit
The script can then be launched with a simple command:
$ expect -f custom.script
You can view a full example in the following page: http://www.journaldev.com/1405/expect-script-example-for-ssh-and-su-login-and-running-commands
Note: The answer proposed by #tripleee would only work if standard input could be read once at the start of the command, or if a tty had been allocated, and won't work for any interactive program.
Example of errors if you use a pipe
echo "su whoami" |ssh remotehost
--> su: must be run from a terminal
echo "sudo whoami" |ssh remotehost
--> sudo: no tty present and no askpass program specified
In SSH, you might force a TTY allocation with multiple -t parameters, but when sudo will ask for the password, it will fail.
Without the use of a program like expect any call to a function/program which might get information from stdin will make the next command fail:
ssh use#host <<'____HERE'
echo "Enter your name:"
read name
echo "ok."
____HERE
--> The `echo "ok."` string will be passed to the "read" command

Eclipse Oxygen: Reading input from a file with <, Run configuration

So in the terminal, I can run my program with
./letter --stack -b ship -e shot -c --output W < input.txt > output.txt
How do I achieve the same functionality in Eclipse? I've figured out how to do --stack -b ship -e shot -c --output W by going to the arguments tab under Run configuration.
I've looked online and seen a lot of posts about using the Common tab to input and output redirection but I can't get it working. When I check only the input file, it doesn't work and the Debug perspective shows it's stuck somewhere trying to read from a stream. When I check allocate console and input file, then it gets stuck on user input (aka I can manually type stuff) in the console.
So how do I get < input.txt and by extension > output.txt working?

Supervisord- Execute a command before starting the application / program

Using supervisord, how do I execute a command before running the program?
For example in the code below, I want a file to be created before starting the program. In the code below I am using tail -f /dev/null to simulate the background process but this could be any running program like '/path/to/application'.
I tried '&&' and this doesn't seem to work. The requirement is that the file has to be created first in order for the application to work.
[supervisord]
nodaemon=true
logfile=~/supervisord.log
[program:app]
command:touch ~a.c && tail -f /dev/null
The problem is that supervisor isn't running a shell to interpret command sections, so "&&" is just one of 5 space separated arguments it is passing to the touch command; if this ran successfully, then there should be some unusual filenames in its working directory now.
You can use a shell as your command and pass it the shell logic you would like:
command=/bin/sh -c "touch ~a.c && tail -f /dev/null"
Usually, this type of shell wrapper should be the interface provided and managed by the app and is what supervisord and others just know how to call with paths and options, i.e.:
command=myappswrapper.sh ~a.c
(where myappswrapper.sh is:)
#!/bin/sh
touch $1 && tail -f /dev/null
Here is a trick.
You use a shell script to do that and beyond that
[program:app]
command:sh /path/to/your/script.sh
It's can your script.sh
touch ~a.c
exec tail -f /dev/null
notice exec

Batch Script input redirection

Trying to run a program within Windows shell and send more input to the program and keep track of the output. Currently when running the program and sending more input it halts within the program expecting input and then the script sends the input after the program is quit.
cd \Users\user\Desktop\program
#echo "To start program, type "program -a [ipaddress] -r [port number] (EG: program -a xx.xx.xx.xx -r 99)"
program -a xx.xx.xx.xx
show devs
the "show devs" command does not show up until the program is quit. How would I properly call this to get "show devs" to be called within the instance of the program?
Pipe it!
echo "show devs" | program -a xx.xx.xx.xx
Check out the info from this pipes and redirect reference.
Also, enjoy the crazy color scheme from 1995.
As #Frozig said, though remember to escape the pipe if running from a batch file.
echo "show devs" ^| program -a xx.xx.xx.xx
If that doesn't work then the input redirection can be done if you are able to let the batch create a small temp file.
cd \Users\user\Desktop\program
echo show devs>tmp.tmp
#echo "To start program, type "program -a [ipaddress] -r [port number] (EG: program -a xx.xx.xx.xx -r 99)"
program -a xx.xx.xx.xx<tmp.tmp
pause
del tmp.tmp