SSH, screen and XDISPLAY - linux

I use screen to persist my work session and connect to the same session from multiple machines. How can I setup SSH and screen such that the XDISPLAY variable inside my persistent screen session is always set to the machine I am currently connecting from?
ie. I start the screen session at work and use gvim, which uses the X server running on my work machine. Later, I connect to the same session from home and also want to use gvim. But this time, I want gvim to use the X server on my home machine. I realize I could manually update XDISPLAY every time I connect from a different machine but I'd rather have an automated system.
Bonus points if I can actually move gvim from my work machine to my home machine while it is running. I tried xmove but could never get it to play nice.

The following is a manual solution, but there's no reason you couldn't
use an alias or a script to have it done automagically when you remotely log in.
Assuming that your local shell sets the DISPLAY variable appropriately,
you could use screen -X to send the following commads to your remote screen before
connecting.
# set future remote shells started by screen to have the correct XDISPLAY
% screen -X "setenv XDISPLAY $DISPLAY" #...
# set up the keystroke F1 to update the XDISPLAY in current shells
% screen -X "bindkey -k k1 stuff export XDISPLAY=$DISPLAY\015" #...
If you know that all your windows were left in a shell (not a running editor or some such), you could use :at to change the XDISPLAY rather than a key binding:
# update the XDISPLAY in all current windows
% screen -X "at % stuff export XDISPLAY=$DISPLAY\015" #...
Alternately, if you know some way of grabbing a parent process's environment variable value, then you could use that together with your shell's prompt hook to grab SCREEN's value of XDISPLAY (as set by setenv) and update it for the shell.

There is no "trivial" way to change environment variables in foreign processes.
A straightforward solution might be to persist your XDISPLAY into a file on login and use a PROMPT_COMMAND to read this file before printing the next prompt.
For moving X applications around look at something like X11vnc or Xvnc.

Related

I want to open terminal sessions that are pre populated with commands on the command line

When I log onto my assorted PCs I usually have a number of things I want to happen automatically, but not always straight away.
These include starting terminal sessions in specific locations on specific desktops (because you get used to using the same layout) and those terminal sessions performing specific acts such as ssh commands. However sometimes when you logon after a reboot you may not want to execute those commands immediately as a higher priority action may need your attention first.
So....what I want is my login script to open terminal sessions and have the session commands pre populated on the command line, but not yet executed.
I use Mate and Compiz as my DE as I like its flexibility.
So in my login script I currently have commands such as.....
mate-terminal --window-with-profile=default --geometry=85x24+180+400 --title='SSH1' &
mate-terminal --window-with-profile=default --geometry=85x24+180+1080 --title='VNC1' &
mate-terminal --window-with-profile=default --geometry=85x24+1305+400 --title='SSH2' &
mate-terminal --window-with-profile=default --geometry=85x24+1305+1080 --title='VNC2' &
These are dedicated mate-terminal sessions that I then enter a ssh and vnc command respectively to connect to some remote boxes. They always open in the same workspace and as can be seen open at a specific location so I always know exactly where I expect them to be.
However I don't want to use the option to say have the ssh command built into the script (as ssh is time sensitive to the receiver and I may not get to it straight away), instead I want to have the command already pre populated in the terminal session so when I do get to it I don't have to type in the whole command each time.
I had looked at using expect to do this and have that working thus
#!/usr/bin/expect -f
# Get a bash shell
spawn -noecho bash
# wait for a prompt
expect ">:"
# type something
send "ssh root#192.168.1.1"
# Hand over control
interact
exit
however I can't see a way of using expect that allows me to spawn the mate-terminal session at specific geometry locations (possibly I'm missing something obvious as I haven't used expect before).
I also don't want to autologon to the ssh sessions using something like a bash 'mate-terminal -c' option as at times the machine may not be network connected which means I'll have a load of potentially messed up attempted connects.
So in recap.
Bash login script.
Opens mate-terminal session at specific geometry locations with command line pre populated with desired command but not yet executed.
Ideas?

How to automatically open prompts, ssh, and do things using a script?

I have to connect to a linux server from my own Ubuntu machine and operate directly on the server.
A dozen of folder names are listed in a LIST file. How to write sth. (like a bash script?) to carry out the following procedures?
for fold_name in LIST {
/******on my own Ubuntu*******/
-- open 2 new tabs of prompt terminal
-- run an ssh command in both
-- then input passwd and log in automatically in both
/******on the linux server*******/
-- cd to directory xxx/fold_name in both
-- run aaa.exe in 1st tab
-- vim sth in the 2nd tab
}
Once the loop of open-tab-login is solved, I guess the second part is routine as simple bash script except that I don't know how to specify between 2 tabs, either.
The point is I want all tabs in the same terminal. To this end, manually, I often Ctrl+Alt+T to create a prompt and Ctrl+Shift+T to open many tabs within it. And ssh...cd...... in each one. You see how annoying and cumbersome it is!
There are a few things you might like to research, which will get you a little closer.
You can run an ssh without a password, if you use an ssh key. Check out ssh-keygen, and the -i option in ssh.
Opening up tabs in gnome-terminal can be done via the method described here: Open a new tab in gnome-terminal using command line
You can run specific commands (e.g. aaa.exe) on a remote box over ssh, by including the command after the ssh: ssh user#remotehost aaa.exe.
If you want multiple commands, try enclosing them in quotes: ssh user#remotehost "cd /xxx; aaa.exe". Vim does not need to be in the directory in question in most cases: ssh user#remotehost vim /xxx/filename"
If you want to do something interactive (like vim), include the -t flag in ssh.
The tabs will be independent of each other - I'd probably run half of the command in one window, the other (e.g. runnning aaa.exe in one window, using one command, and the vim in another window, using another command, that I just happen to run at the same time. This way I can resize the windows, and arrange them relative to each other, and see both at once.
-- open 2 new tabs of prompt terminal
This depends on which desktop you're using. For gnome, gnome-terminal takes the -e option to specify the script to execute in the new terminal window. So, for something like this, you would execute gnome-terminal -e $script &, placing each instance of gnome-terminal in the background.
If you're using a different desktop, other terminal applications typically have a similar option. So, you'd point the terminal application to a script that's going to run in the terminal, and complete the rest of your task for you.
-- run an ssh command in both
-- then input passwd and log in automatically in both
This is going to be more complicated. The classical solution is the expect utility. There might be other similar tools that do similar things, but expect is pretty much the usual way these kinds of things have been done in the past. When it comes to trying to automate an interactive application, expect is really the only way to go. Unfortunately, expect uses a somewhat arkane syntax, that first-time users typically find confusing, and hard to understand. I grumble, every time I see no other alternative but to use expect to automate something, but this is pretty much the only option that's usually available.

How to make GNU screen auto start when login?

I have several linux servers to work on every day, and I have a GNU screen session on each of them to preserve work progress.
The question is I am so tired of issue screen -Rd work every time I login, is there anyways to get rid of that? Or any workarounds?
Reading #Sami's answer, I did some search on the $STY shell variable and found this:
STY: Alternate socket name. If screen is invoked, and the environment variable STY is set, then it creates only a window in the running screen session rather than starting a new session.
So I think the key is the $STY variable, we may append it to either .bashrc or .profile, as long as it gets executed upon login. Thanks #Sami
This depends on your shell. In case you use any of Bourne Shell derivatives (namely Bash) or Bourne Shell itself, put appropriate commands in ~/.profile:
[ -z "$STY" ] && screen -Rd "work"
This will only start a screen session in case you're not already running inside a screen session (screen sets environment variable STY).
In case you're not using Bash or compatible, use the proper shell initialization file with a similar test.
You could put an alias in your login script:
alias s="screen -Rd work"
then you'd only have to type
s

How do I get GNU screen to read .bash_profile/.bash_rc changes?

After I make changes in .bash_rc or .bash_profile, when I start GNU screen, it doesn't recognize those changes.
I can
source ~/.bash_profile
and it works for the current screen window I have open, but I have to do that for every screen window I have open.
How do I get screen to read my latest changes in my bash configuration?
If you want screen to always treat your shell as a login shell, and source the same files that would be read if just started a new shell normally, add the following to ~/.screenrc (or maybe ~/.byobu/.screenrc, as pointed out in the comment):
shell -$SHELL
This way, you don't need to manually tell it to source your files each time you start a new screen. Though you would have to if you just made changes and wanted those changes to be reflected in your current screen.
The documentation for this (and lots of other screen details) can be found here. Basically, shell is a command to screen telling it to run the following when it needs to create a new shell. $SHELL is the usual variable holding the path to your preferred shell. And the dash - in front of $SHELL indicates that it should be run as a login shell (which will typically mean it sources your ~/.bash_profile, etc.).
It's worth pointing out, however, that screen defaults to just inheriting most environment variables from the shell where you start screen; and a login sub-shell may alter some environment variables in unexpected ways. I ran into a situation where elements of my $PATH were basically permuted. I solved the problem thanks to this particularly excellent answer on superuser.
You may notice the source command available. It's important to note that this sources a file of screen commands, rather than shell commands. Other relevant (screen) commands include eval and exec.
You have to do it in each screen that you have open since they are all different shells. If you need the change every time a new shell is opened, I suggest you put the changes in ~/.bashrc instead.
Apparently, you can send a command to all windows at once using this syntax:
C-a :
at "#" stuff "source ~/.bash_profile^M"

Run a command in a shell and keep running the command when you close the session

I am using Putty to connect to a remote server. What I want to know is if there is any way to write my commands and allow them to keep running after I close the session with Putty. The reason for this is that I do not want to keep the computer ON all the time. Is there any way to do this?.
Update with the solution
For my question as it is presented the best solution is use one of the commands provided such as nohup, because you do not have to install any additional software. But if you are in the same problem use screen, install it and use it. It is amazing.
I have selected the answer of Norman Ramsey as favourite because propose several solutions using commands and screen. But please check the other answers specially the one of PEZ, then you get an insight of what screen is able todo.
screen! It's the best thing since sliced bread. (Yeah, I know others have already suggested it, but it's so good the whole world should join in and suggest it too.)
screen is like, like, ummmm ... like using VNC or the like to connect to a GUI destop, but for command shell windows. You can have several shell "windows" open at once in the same screen session. You can do stuff like:
Start a screens session using "screen -dR" (get used to using -dR)
run some commands in one window
press CTRL-A,C to create a new window open a file there in vim
press CTRL-A,0 to go back to the first window and issue some command on the file you just edited
CTRL-A, 1 to go back to your vim session
CTRL-A, C for yet another window and maybe do "sudo - su" (because you just happen to need a full root shell)
CTRL-A, 0 and start a background process
CTRL-A, C to create yet a new window, "tail -f" the log for that background process
CTRL-A, d to disconnect your screen then CTRL-D to disconnect from the server
Go on vacation for three weeks
Log on to the server again and issue "screen -dR" to connect to your existing screen session
check the log in the the fourth window with CTRL-A, 3 (it's like you've been there watching it all the time)
CTRL-A, 1 to pick up that vim session again
I guess you're starting to get the picture now? =)
It's like magic. I've been using screen for longer than I can remember and I'm still totally amazed with how bloody great it is.
EDIT: Just want to mention there's now also tmux. Very much like screen, but has some unique features, splitting the windows being the most prominent one.
nohup, disown, and screen are all good but screen is the best because unlike the other two, screen allows you to disconnect from the remote server, keep everything running, and then reconnect later to see what is happening. With nohup and disown you can't resume interacting.
Try using GNU Screen. It allows you to have several shells open at once. And you can disconnect from those running shells (i.e. close session with Putty) and they will keep doing their thing.
What you are looking for is nohup.
See the wiki link for how to use it.
screen is the best.
Try:
screen -dmS "MyTail" tail -f /var/log/syslog
This start command in background.
Use screen -r to list, and or screen -r Mytail to enter session.
If more users need access same session, use: screen -rx MyTail, and both or more users share the session.
If you can't use screen (because, for instance, your SSH session is being programmatically driven), you can also use daemonize to run the program as a daemon.
One way that works well for me is at.
at works like cron, but for a one-time job. I used it today to download a large file without having to keep my session alive.
for example:
$ at 23:55
at> wget http://file.to.download.com/bigfile.iso
at> ^D
You pass at a time (in the future) and it gives you a prompt. You enter the commands you want to run at that time and hit ctrl+d. You can exit out of your session and it will run the commands at the specified time.
Wikipedia has more info on at.
./command & disown
ssh localhost && ./command && exit

Resources