Is it possible to create a screen and execute a command in it without actually open it?
What I need to perform is the following:
Open a screen (screen -S screen_name)
Execute command in that screen
At the moment I need to manually create the screen, then enter it, and then execute the desired command.
Is it possible to do that only via 1 bash command?
Create a screen with in detached mode:
screen -S "scr1" -d -m
Send the command to be executed on your screen:
screen -r "scr1" -X stuff $'ls -lrt \n'
The $ before the command is to make the shell parse the \n inside the quotes, and the newline is required to execute the command (like when you press enter).
Related
Using tmux, I'd like to run a command from one pane against another pane, and capture the output of the command.
For example, say in pane 7 I have an SSH session running, and I'd like to run a bash script in pane 2 to capture the host name from pane 7.
Is this possible?
I know I can do the send keys like so
$ tmux send-keys -t 7 "hostname" Enter
but I'm not sure how to capture the output from pane 7 into a bash variable.
I don't mind if it displays on the screen either (doesnt have to happen in the background).
EDIT: Note that hostname is just an example - I would like to run other scripts against each pane as well
As an alternative to capture-pane you can similarly use pipe-pane. It is often used for logging. You give it a command to pipe all output into, or no command at all to stop piping. So you end up with something like
tmux pipe-pane -t 7 'cat >/tmp/capture'
tmux send-keys -t 7 'hostname' Enter
sleep 1
tmux pipe-pane -t 7 # stops piping
IT=$(</tmp/capture)
Beware, this capture includes carriage-return characters. You will need to remove the first and last lines of the capture to get just the wanted output. Eg:
IT=$(sed '1d;$d;s/\r//' </tmp/capture)
While not exactly what I was looking for, the tmux capture-pane command seems to capture the displayed output of a pane, which I can run of course after running my command.
example.sh
#/bin/bash
# run the command in another pane
tmux send-keys -t 7 "hostname" Enter
# capture it's output
IT=$(tmux capture-pane -p -t 7)
echo "$IT"
I'm trying to run a command on detached Screen. The problem is that it does not work when the command has additional parameters, e. g.:
screen -L "ls"
It produces a file (screenlog.0) with directory listing. But when I'm running
screen -L "ls -la"
Screen fails with error: Cannot exec 'ls -la': No such file or directory
Is there any way to run it properly in a Screen session?
You should use screen without quotes, then should be ok.
I want to use the screen -x command to enter a screen then run a command. I thought this would be easy:
screen -x
cd /ftb
java -Xms2048m -Xmx2048m -jar mcpc.jar
However that didn't work. It outputs the screen help and says Error: Unknown option x and : No such file or directory 2: cd: /ftb (including the :)
First, your script file has DOS line endings; the unknown option is actually -x\r. You'll need to remove them, either by saving the file in your editor with UNIX line endings or running dos2unix on the file
Second, when screen -x succeeds, you are attached to the screen session, and the screen -x command will not exit until you detach, at which point your script can continue with the cd command. I think what you actually want is the -X option, which sends a command to an existing session.
screen -X 'cd /ftb; java -Xms2048m -Xmx2048m -jar mcpc.jar'
screen -x
Send the command to the session, then attach to it.
I am trying to send input to a interactive command running via screen. Here is my initial command
screen -L -c ./customrc -S psql -d -m /opt/PostgreSQL/9.0/bin/psql
The above command will run interactive psql in screen detach mode. The customrc is used to define a log file for the output (which I will read from another process by polling)
I am using following two commands to send input to psql running in screen
screen -S psql -X readreg p psqlcommands.sql
screen -S psql -X paste p
The problem is that the above commands do not work unless I reattach screen at least once. Once I have attached screen and detached, the above commands work as expected. I have to launch these commands via background java process hence the interactive shell (bash) is not available. My goal is to run psql in interactive mode and pass input to it and capture its output via a log file.
So far I have tried to run screen via xterm (or konsole or gnome-terminal) in attach mode, use readreg/paste and then detach, but I realise that xterm will not be available in my production environment. I've also tried sending output to /proc//fd/0 but I am unable to emulate 'ENTER' from keyboard (I have to attach and press in order for the output to be accepted by psql). I think pipes and fifo may help but I am unable to figure out how to proceed with them using screen and psql.
I appreciate any further hints or workarounds.
Thank you,
Usman.
Well, you can use
screen -S psql -p 0 -X stuff $'\n'
or better (works for me)
screen -S mname -p 0 -X stuff `echo -ne '\015'`
-p 0 is needed to select the window.
Have you tried this to "press enter" after your readreg and paste?
screen -S psql -X stuff $'\n'
FINAL ANSWER: It is a bug/feature in 'GNU screen' that it needs a DISPLAY atleast once for 'paste' command to work. Following are possible workarounds this problem:
Finally figured out how to utilise psql with pipes and screen. Here is the solution:
mkfifo psql.pipe
screen -L -c ./customrc -S psql -d -m bash -i -c "while (true); do cat psql.pipe; done | /opt/PostgreSQL/9.0/bin/psql -a"
After that, I can cat my commands to the pipe:
cat ./mycommands.sql > psql.pipe
To quit from screen and terminating psql, I used
screen -S psql -X quit
EDIT: (finally) figured out the solution for my problem without using screen command. Meet 'empty' utility.
empty -f -i psql.in -o psql.o -p psql.pid <psqlpath>
This allows psql to run in full interactive mode as opposed to the original solution that I used (in which psql does not run in interactive mode).
Thanks.
Usman
I had this same problem. My workaround was to launch screen attached but pass it a screenrc file where the last command is "detach"
So this is my screenrc
#change the hardstatus settings to give an window list at the bottom of the
#Set this first otherwise messes with bash profile
hardstatus alwayslastline
#screen, with the time and date and with the current window highlighted
#hardstatus string '%{= kG}%-Lw%{= kW}%50> %n%f* %t%{= kG}%+Lw%< %{= kG}%-=%c:%s%{-}'
hardstatus string '%{= kG}[ %{G}%H %{g}][%= %{= kw}%?%-Lw%?%{r}(%{W}%n*%f%t%?(%u)%?%{r})%{w}%?%+Lw%?%?%= %{g}][%{B} %m-%d %{W}%c %{g}]'
#set scrollback
defscrollback 4096
#detach
detach
Hope this helps
P
According to the docs for the Unix "screen" command, you can configure it in .screenrc to start with a bunch of default screens, each running a command that you specify.
Here's my cofig:
# Default screens
screen -t "shell_0" 1
screen -t "autotest" 2 cd ~/project/contactdb ; autotest
It will not run the autotest command. That window where I'm trying to run autotest just closes instantly when I start screen.
I also tried it with just...
screen -t "autotest" 2 cd ~/project/contactdb
Same result.
I also tried...
screen -t "autotest" 2 ls
Same result there too.
What's the secret to getting it to run a command in a given screen on startup?
Your program is being run (well, except the cd), it's just that it's being run without a parent shell, so as soon as it completes, it exits and you're done.
You could do:
screen -t "autotest" 2 bash -c 'cd ~/project/contactdb ; autotest'
Spawns two shells, but life will probably go on.
Try this:
$ screen -S 'tailf messages' -d -m tailf /var/log/messages
Then later you can do:
$ screen -ls
1234.tailf messages
Followed by:
$screen -r 1234
This might help but may not be entirely what you want.
Put "zombie az" or "defzombie az" as the first line of your .screenrc. "az" can be whatever 2 keys you'd like. Now, when a screen ought to close (command finished executing, for instance), it won't actually close; hitting 'a' will close it, hitting 'z' will re-execute the command attached to that screen.
I found that at the screen user's manual.
You can also "stuff" characters into the screen as if you had typed them.
Here's how you can do that with your example:
screen -t "shell_0" 1
# create the following screen in the desired dir, instead of cd-ing afterwards :)
chdir ~/project/contactdb
screen -t "autotest" 2
# (without this sometimes screens fail to start correctly for me)
sleep 5
# paste some text into screen number 2:
select 2
stuff "autotest\012"
Here's how mine looks. It seems to work fine. I think either the parenthesis might be causing the problem or screen will not open a window if the command "autotest" does not exist.
screen -t zsh 1
screen -t emacs 2 emacs -nw
screen -t mutt 3 mutt
monitor on
screen -t mc 4 mc -s
screen -t elinks 4 elinks
Here's how I'd do it.
screen -t shell_0
chdir ~/project/contactdb
screen -t autotest autotest
The above appears to be evaluated procedurally by screen. First we establish a new screen with the title shell_0. Since we gave no other options, current working directory will be that of the parent shell or the user's home directory. We then set the default directory for new screens to ~/project/contactdb. Next, we establish a new screen running the autotest command.
Window number (n) is optional, I generally omit it.