I'm running zsh as the default shell on a Ubuntu box, and everything works fine using gnome-terminal (which as far as I know emulates xterm). When I login from a windows box via ssh and putty (which also emulates xterm) suddendly the home/end keys no longer work.
I've been able to solve that adding these lines to my zshrc file...
bindkey '\e[1~' beginning-of-line
bindkey '\e[4~' end-of-line
...but I'm still wondering what's wrong here. Any idea?
I found it's a combination:
One
The ZSH developers do not think that ZSH should define the actions of the Home, End, Del, ... keys.
Debian and Ubuntu fix this by defining the normal actions the average user would expect in the global /etc/zsh/zshrc file. Following the relevant code (it is the same on Debian and Ubuntu):
if [[ "$TERM" != emacs ]]; then
[[ -z "$terminfo[kdch1]" ]] || bindkey -M emacs "$terminfo[kdch1]" delete-char
[[ -z "$terminfo[khome]" ]] || bindkey -M emacs "$terminfo[khome]" beginning-of-line
[[ -z "$terminfo[kend]" ]] || bindkey -M emacs "$terminfo[kend]" end-of-line
[[ -z "$terminfo[kich1]" ]] || bindkey -M emacs "$terminfo[kich1]" overwrite-mode
[[ -z "$terminfo[kdch1]" ]] || bindkey -M vicmd "$terminfo[kdch1]" vi-delete-char
[[ -z "$terminfo[khome]" ]] || bindkey -M vicmd "$terminfo[khome]" vi-beginning-of-line
[[ -z "$terminfo[kend]" ]] || bindkey -M vicmd "$terminfo[kend]" vi-end-of-line
[[ -z "$terminfo[kich1]" ]] || bindkey -M vicmd "$terminfo[kich1]" overwrite-mode
[[ -z "$terminfo[cuu1]" ]] || bindkey -M viins "$terminfo[cuu1]" vi-up-line-or-history
[[ -z "$terminfo[cuf1]" ]] || bindkey -M viins "$terminfo[cuf1]" vi-forward-char
[[ -z "$terminfo[kcuu1]" ]] || bindkey -M viins "$terminfo[kcuu1]" vi-up-line-or-history
[[ -z "$terminfo[kcud1]" ]] || bindkey -M viins "$terminfo[kcud1]" vi-down-line-or-history
[[ -z "$terminfo[kcuf1]" ]] || bindkey -M viins "$terminfo[kcuf1]" vi-forward-char
[[ -z "$terminfo[kcub1]" ]] || bindkey -M viins "$terminfo[kcub1]" vi-backward-char
# ncurses fogyatekos
[[ "$terminfo[kcuu1]" == "^[O"* ]] && bindkey -M viins "${terminfo[kcuu1]/O/[}" vi-up-line-or-history
[[ "$terminfo[kcud1]" == "^[O"* ]] && bindkey -M viins "${terminfo[kcud1]/O/[}" vi-down-line-or-history
[[ "$terminfo[kcuf1]" == "^[O"* ]] && bindkey -M viins "${terminfo[kcuf1]/O/[}" vi-forward-char
[[ "$terminfo[kcub1]" == "^[O"* ]] && bindkey -M viins "${terminfo[kcub1]/O/[}" vi-backward-char
[[ "$terminfo[khome]" == "^[O"* ]] && bindkey -M viins "${terminfo[khome]/O/[}" beginning-of-line
[[ "$terminfo[kend]" == "^[O"* ]] && bindkey -M viins "${terminfo[kend]/O/[}" end-of-line
[[ "$terminfo[khome]" == "^[O"* ]] && bindkey -M emacs "${terminfo[khome]/O/[}" beginning-of-line
[[ "$terminfo[kend]" == "^[O"* ]] && bindkey -M emacs "${terminfo[kend]/O/[}" end-of-line
fi
So, if you are connecting to a Debian or Ubuntu box, you don't have to do anything. Everything should work automagically (if not, see below).
But... if you are connecting to another box (e.g. FreeBSD), there might be no user friendly default zshrc. The solution is of course to add the lines from the Debian/Ubuntu zshrc to your own .zshrc.
Two
Putty sends xterm as terminal type to the remote host. But messes up somewhere and doesn't send the correct control codes for Home, End, ... that one would expect from an xterm. Or an xterm terminal isn't expected to send those or whatever... (Del key does work in xterm however, if you configure it in ZSH). Also notice that your Numpad-keys act funny in Vim for example with xterm terminal.
The solution is to configure Putty to send another terminal type. I've tried xterm-color and linux. xterm-color fixed the Home/End problem, but the Numpad was still funny. Setting it to linux fixed both problems.
You can set terminal type in Putty under Connection -> Data. Do not be tempted to set your terminal type in your .zshrc with export TERM=linux, that is just wrong. The terminal type should be specified by your terminal app. So that if, for example, you connect from a Mac box with a Mac SSH client it can set it's own terminal type.
Notice that TERM specifies your terminal type and has nothing to do with the host you are connecting to. I can set my terminal type to linux in Putty and connect to FreeBSD servers without problems.
So, fix both these things and you should be fine :)
On the PuTTY configuration dialog, go to Connection -> Data and type linux into the Terminal-type string before connecting.
This is working for me
bindkey -v
bindkey '\eOH' beginning-of-line
bindkey '\eOF' end-of-line
It's now been nearly 11 years since this question was first posted. At the time, some distros did ship with a putty terminfo entry, but it was mediocre at best. In the years since, the situation has improved, and the hacks that were necessary for over a decade are no longer required. PuTTY still defaults to setting TERM to xterm for compatibility, but if you're connecting to modern, up-to-date systems, you'll likely have luck overriding this and setting it to putty-256color:
Ensure the host has a terminfo entry for putty-256color: toe -a | grep -F putty
Undo any hacks you may have enabled to get PuTTY working properly with zsh or other programs.
Ensure PuTTY is up-to-date. It won't notify you when updates are available, and if it's out-of-date, you're likely going to run into a lot of the same issues. You may want to keep it up-to-date automatically with something like Chocolatey.
In PuTTY's configuration dialog, go to Connection -> Data and set "Terminal-type string" to putty-256color.
While you're at it, on the same configuration screen, add a new environment variable to enable 24-bit color. This variable isn't standardized, but it's sent by a number of other mainstream terminal emulators (e.g., iTerm2), and many programs understand it.
Variable: COLORTERM
Value: truecolor
As of writing, I haven't found a distro that accepts the COLORTERM variable over SSH by default. You'll need to edit your OpenSSH configuration on the host to allow it. For example, on Debian-like distros, edit /etc/ssh/sshd_config and add COLORTERM to the AcceptEnv line.
Everything should now "just work". If it doesn't:
Ensure you've reconnected after making the change, or at least run exec zsh after changing TERM. zsh won't react to changes in TERM while it's running.
Ensure that TERM is actually set to what you intended: echo $TERM
Are you on the latest version of your distro? If you're on a long-term support lifecycle build, for example, even if your version is technically still supported, it may not have up-to-date terminfo entries.
Are you using screen or tmux? That's another whole can of worms. Test without those first to narrow down where the issue is occurring. Within tmux, try setting TERM=tmux-256color. Within screen, try TERM=screen-256color.
Are you on the latest version of PuTTY?
Do you have RC-files that are implementing keybindings or other hacks? Try using default RC-files.
Did you already change various PuTTY settings to attempt to fix the issue before attempting the terminfo fix? You'll probably need to reset those settings.
the appropriate answer that should be portable across all distros (not necessarly all versions of zsh though, ymmv here) is to use the zkbd helper utility from zkbd.
Keyboard Definition
The large number of possible combinations of keyboards, workstations, terminals, emulators, and window systems makes it impossible for zsh to have built-in key bindings for every situation. The zkbd utility, found in Functions/Misc, can help you quickly create key bindings for your configuration.
Run zkbd either as an autoloaded function, or as a shell script:
zsh -f ~/zsh-4.3.17/Functions/Misc/zkbd
When you run zkbd, it first asks you to enter your terminal type; if the default it offers is correct, just press return. It then asks you to press a number of different keys to determine characteristics of your keyboard and terminal; zkbd warns you
if it finds anything out of the ordinary, such as a Delete key that sends neither ^H nor ^?.
The keystrokes read by zkbd are recorded as a definition for an associative array named key, written to a file in the subdirectory .zkbd within either your HOME or ZDOTDIR directory. The name of the file is composed from the TERM, VENDOR and OSTYPE
parameters, joined by hyphens.
You may read this file into your .zshrc or another startup file with the source or . commands, then reference the key parameter in bindkey commands, like this:
source ${ZDOTDIR:-$HOME}/.zkbd/$TERM-$VENDOR-$OSTYPE
[[ -n ${key[Left]} ]] && bindkey "${key[Left]}" backward-char
[[ -n ${key[Right]} ]] && bindkey "${key[Right]}" forward-char
# etc.
Note that in order for autoload zkbd to work, the zkbd file must be in one of the directories named in your fpath array (see zshparam(1)). This should already be the case if you have a standard zsh installation; if it is not, copy Functions/Misc/zkbd to an appropriate directory.
see man -P "less -p 'keyboard definition'" zshcontrib, or search the meta-manpage zshall
It seems a putty thing. Gnome-terminal sends the codes ^[OH and ^[OF for Home and End respectively, while putty sends ^[[1~ and ^[[4~. There's an option in putty to change the Home/End keys from standard mode to rxvt mode, and that seems to fix the Home key, but not the End key (which now sends ^[Ow). Guess it's time to file a bug report somewhere... :-)
These bindings simply don't appear to be part of the default bindings set in emacs mode.
executing "where-is beginning-of-line" on my default zsh installation after running "bindkey -e" shows it is only bound to ^a. Perhaps you should ask the zsh developers why :-)
This worked for me.
Adding these lines to ~/.zshrc
bindkey "\e[1;5D" backward-word
bindkey "\e[1;5C" forward-word
# ctrl-bs and ctrl-del
bindkey "\e[3;5~" kill-word
bindkey "\C-_" backward-kill-word
# del, home and end
bindkey "\e[3~" delete-char
bindkey "\e[H" beginning-of-line
bindkey "\e[F" end-of-line
# alt-bs
bindkey "\e\d" undo
Related
# allow CTRL-Q and CTRL-S keybindings
vim() {
(
# No ttyctl, so we need to save and then restore terminal settings
# osx users, use stty -g
local STTYOPTS="$(stty --save 2> /dev/null)"
trap "stty $STTYOPTS" EXIT
stty stop '' start '' -ixoff
command vim "$#"
)
}
I'm using the above shell function to temporarily change stty options so that CTRL-Q and CTRL-S can function as keybinds in vim.
This works nicely, but as a side-effect I can no longer see which file corresponds to a background job when I pause vim with CTRL-Z. I frequently work with multiple sessions in the background and it would be really handy to be able to see which job is which again.
Current output from jobs with a background task:
root#rock64:~# jobs
[1]+ Stopped ( local STTYOPTS="$(stty --save 2> /dev/null)"; trap "stty $STTYOPTS" EXIT; stty stop '' start '' -ixoff; command vim "$#" )
root#rock64:~#
Unwrapped output like this would be ideal:
root#rock64:~# jobs
[1]+ Stopped vim .bashrc
root#rock64:~#
Is there a different way to achieve the same effect (temporarily changing STTY options with restore on job completion) without squashing the background jobs listing?
I'm running Bash 4.4.x at the moment but I could easily compile a newer version if needed.
So what I am suggesting in the comment is difficult to convey without better code formatting. I am simply suggesting removing the surrounding ( and ). Additionally, the RETURN trap would need to be removed, so I just made a second function that, when return is called, we jump back to the original function and remove the trap.
runvim() {
local STTYOPTS="$(stty --save 2> /dev/null)"
trap "stty $STTYOPTS" RETURN # This may need to be changed to RETURN
stty stop '' start '' -ixoff
command vim "$#"
}
# allow CTRL-Q and CTRL-S keybindings
vim() {
# No ttyctl, so we need to save and then restore terminal settings
# osx users, use stty -g
runvim "$#"
trap - RETURN
}
Alternative
You could put this in a script called vim in $HOME/bin:
#!/bin/bash
STTYOPTS="$(stty --save 2> /dev/null)"
trap "stty $STTYOPTS" EXIT
stty stop '' start '' -ixoff
#/usr/bin/vim "$#" # or where ever your vim is
$( whereis vim | cut -d\ -f3) "$#" # Here is a more generic version.
Then add that directory to the front of your PATH variable by adding export PATH="$HOME/bin:$PATH" to your favorite dot file.
Edit:
I went ahead and improved the wrapper to look for the next real vim in the path if it's run as a symlink called 'vim' in the user path. This avoids needing to use an alias pointing 'vim' at vimwrapper.sh and transparently forwards 'vim' calls to the actual vim binary. I think this is basically complete now.
#!/usr/bin/env bash
#
# vimwrapper.sh: Wrapper script to enable use of CTRL-Q/S keybinds in Vim
#
# Using a wrapper script avoids clobbering the editor command line with an
# anonymous subshell that's hard to read when vim is suspended with ^Z. We need
# the scope of the subshell to trap our trap (aaayyyyy) and keep the stty magic
# out of our interactive environment's namespace. The wrapper script just
# makes background jobs look sane if you interrupt vim with CTRL-Z.
# set -x
case $(basename "$0") in
"vim")
# Check if we're shadowing real vim by existing earlier in the path as a
# symlink and call it directly if so. This lets us symlink vimwrapper.sh to
# "$HOME/bin/vim", munge "$HOME:/bin" onto the beginning of the path and
# transparently wrap calls to 'vim' without our script going recursive.
for _v in $(which -a "vim"); do
# I refuse to fork myself. You know what, fork you too.
[[ $(realpath "$_v") == $(realpath "$0") ]] && continue
#printf "found real vim in path at '%s'\n" "$(realpath $_v)"
cmd="$_v" && break
done
if [[ -z "$cmd" ]]; then
echo "$(basename $0): Unable to find real vim in path"
exit 1
fi
;;
*)
cmd="vim"
;;
esac
STTYOPTS="$(stty --save 2> /dev/null)"
trap "stty $STTYOPTS" EXIT
stty stop '' start '' -ixoff
command "$cmd" "$#"
Original post:
After playing with this for a while today I think I've got a decent solution. A subshell is necessary to scope/contain the stty parameter changes and the vim process that we want effected by them, but it doesn't have to be an anonymous function in the main shell environment.
#!/usr/bin/env bash
#
# vimwrapper.sh: Wrapper script to enable use of CTRL-Q/S keybinds in Vim
# For best results bind 'alias vim="/path/to/vimwrapper.sh"
#
# Using a wrapper and alias avoids clobbering the editor command line with an
# anonymous subshell that's hard to read when vim is suspended with ^Z. We need
# the scope of the subshell to trap our trap (aaayyyyy) and keep the stty magic
# out of our interactive environment's namespace. The wrapper script just
# makes background jobs look sane if you interrupt vim with CTRL-Z.
# We'll be paranoid and make sure our wrapper script isn't the target of the
# 'command vim' call that comes next.
if [[ $(realpath $(basename "$0")) == $(realpath $(which vim)) ]]; then
echo "$0: I refuse to fork myself. You know what, fork you too."
else
# Save stty state and restore on exit.
STTYOPTS="$(stty --save 2> /dev/null)"
trap "stty $STTYOPTS" EXIT
stty stop '' start '' -ixoff
command vim "$*"
fi
exit 0
Binding a call to the wrapper script as alias vim="~/foo/vimwrapper.sh" takes care of everything nicely:
root#rock64:~/bin# vim vim.sh
[1]+ Stopped ~/bin/vim.sh vim.sh
It's possible to symlink vimwrapper.sh as 'vim' somewhere in the path provided its location has a lower priority than real vim's too. I added a check for that so it doesn't go recursive by accident. I'll probably expand that a little bit so the script can shadow the real vim in the path and figure out which is the right command to call by looking at which -a vim and picking the next entry that isn't itself.
Thanks #Jason for pointing me in the right direction, I really appreciate it.
In tcsh, how to set bind-key for general command like cd or ps ?
I was trying bindkey "^G" "cd ../../" I get error Bad Command name: cd
I have looked at few online example. Its working when I want to do something, history search forward or end of line. But I want to do it for some other common command which I execute thousands of time in given day. e.g I use CD or ps command very often. I wanted to set bindkey for such commands ?
You can use the -c flag when setting bindkeys for external commands. For instance: bindkey -c "^]^d" "ls /" will bind Ctrl+]+d to spit out the contents of the root directory.
In your case:
bindkey -c "^G" 'cd ../../'
One caveat here is that your shell prompt may not update upon execution via the bindkey. So you will have traversed your two parent directories, but your shell prompt may still indicated that you are sitting in the directory from which you used the bindkey, even though you aren't.
I'm familiar with methods that rely on .bashrc across both platforms, but then there's always folks that have ZSH (.zshrc), and I'm wondering what the best way to check / identify the place to update a PATH variable permanently is across OSX and Linux, specifically from a Bash script, for at least these two types of terminals. Not sure if I need to do some sort of nested IF THENS, or if something is out there that is kind of elegant. Thanks.
There's a system wide profile at /etc/profile that you can use to set variables. Of course, you need root permission to do it.
This will work for bash users and zshell users, with the example in this case of adding miniconda, but you can change the value for DIRECTORY_TO_APPEND_TO_PATH pretty easily...
update_script_startup_file() {
DIRECTORY_TO_APPEND_TO_PATH="\$HOME/miniconda/bin"
echo "if [[ \":\$PATH:\" != *\":$DIRECTORY_TO_APPEND_TO_PATH:\"* ]]; then" >> $STARTUP_FILE
echo " export PATH=\"\$PATH:$DIRECTORY_TO_APPEND_TO_PATH\"" >> $STARTUP_FILE
echo "fi" >> $STARTUP_FILE
}
if [ -n "`$SHELL -c 'echo $BASH_VERSION'`" ]; then
STARTUP_FILE="$HOME/.bashrc"
update_script_startup_file
elif [ -n "`$SHELL -c 'echo $ZSH_VERSION'`" ]; then
STARTUP_FILE="$HOME/.zshrc"
update_script_startup_file
else
echo "Couldn't automatically add Miniconda to the PATH of your preferred terminal. We suggest working from Bash or ZShell."
fi
If anyone wants to edit this to add support for other shells, they're most welcome to!
I'm currently using tmux with xterm-256color $TERM variable. When in bash under tmux, pressing home/end would insert tilde characters (~). Outside of tmux the home/end keys work fine.
Using cat and tput, I could see that there was a mismatch between the generated and expected sequences:
$ cat -v # pressing home, then end
^[[1~^[[4~
$ tput khome | cat -v; echo
^[OH
$ tput kend | cat -v; echo
^[OF
To fix this, I decided to add the following to my .bashrc:
if [[ -n "$TMUX" ]]; then
bind '"\e[1~":"\eOH"'
bind '"\e[4~":"\eOF"'
fi
That fixed the problem for bash, however in other readline programs, such as within a REPL such as ipython, it still inserts a tilde for home/end.
Why exactly is this a problem in the first place? Why is the generated sequence different when I'm inside tmux vs outside it? How can fix this so that it's not an issue in any programs?
It appears the main problem is with using xterm-256color for $TERM. I switched $TERM to screen-256color and the problem went away.
Add the following to your .tmux.conf:
bind-key -n Home send Escape "OH"
bind-key -n End send Escape "OF"
And you're done!
Explanation
After attempting each one of these, and several others I saw while perusing other answers and documentation, this finally worked for me in every scenario I threw at it. I can't promise the same for you, because everyone's scenarios are different, but this is what I ended up with.
This was discovered after introducing the same trial/error and logic from a somewhat relevant article that is no longer available. The key is where the translation is occurring; in my case, this happens within my .tmux.conf, rather than .bashrc or .zshrc (mainly because my home/end worked fine outside of tmux)
Debugging
You can debug this issue by using cat -v.
Run cat -v, then press the Home and End keys. Exit using Ctrl+C.
$ cat -v
Here's what my output looked like within tmux using zsh, zsh, and bash:
tmux
➜ ~ cat -v
^[[1~^[[4~^C
zsh
➜ ~ cat -v
^[[H^[[F
bash
bash-3.2$ cat -v
^[[H^[[F
Solutioning
Compare the above examples to what we're expecting to see, by pairing tput with cat -v:
$ tput khome | cat -v; echo
^[OH
$ tput kend | cat -v; echo
^[OF
Conclusion
Because this problem exists solely within tmux, and not within the shells themselves, I opted to make the bind changes within the tmux configuration instead. By using bind-key paired with send, we can use the Escape keyword paired with the sequence we want to achieve our translation. Thus:
bind-key -n NAME_OF_KEY send Escape SEQUENCE_GOES_HERE
This debugging and solutioning process can be applied to any other key translation issues. But, don't go too crazy. Some keys are mapped to certain escape sequences for a reason. Notice how bash and zsh received the ^[[H sequence for Home instead of ^[OH; it's probably not recommended we override this in our .zshrc unless we're having major issues with this in zsh.
In tmux 2.0, you can just add these 2 lines in your .tmux.conf:
bind -n End send-key C-e
bind -n Home send-key C-a
If you want to stay with xterm-256color in tmux for some reason - use arch solution with inputrc. I tested it in tmux with rxvt, ruby irb, python, lua and home/end keys are ok. Probably every readline app will be ok.
From the arch wiki:
First things first:
do not set $TERM manually - let the terminal do it.
Many command line applications use the Readline library to read input. So properly configuring Readline can fix Home and End in many cases.
the default /etc/inputrc file does not include a mapping for home/end keys.
To check what the emitted escape sequence for these keys is:
1. Ctrl + V
2. Home
3. Spacebar
4. Ctrl + V
5. End
this will probably print: $ ^[[1~ ^[[4~. So you have to add a mapping for these sequences to your inputrc (/etc/inputrc to be globally, or only for your user ~/.inputrc):
"\e[1~": beginning-of-line
"\e[4~": end-of-line
In my case it was a problem with zsh in tmux (bash in tmux was ok).
None of the other anwsers here worked for me.
But adding this to .zshrc fixed it:
bindkey "\E[1~" beginning-of-line
bindkey "\E[4~" end-of-line
Besides that I also have:
bindkey "\E[H" beginning-of-line
bindkey "\E[F" end-of-line
bindkey "\E[3~" delete-char
From tmux FAQ:
PLEASE NOTE: most display problems are due to incorrect TERM! Before
reporting problems make SURE that TERM settings are correct inside and
outside tmux.
Inside tmux TERM must be "screen", "tmux" or similar (such as
"tmux-256color"). Don't bother reporting problems where it isn't!
Outside, it should match your terminal: particularly, use "rxvt" for
rxvt and derivatives.
Add the following command to your ~/.tmux.conf:
set -g default-terminal tmux-256color
PS: any solution involving binding the keys explicitly is a hack, and as such bound to fail.
set-window-option -g xterm-keys on
This should work in tmux 2.6 and later. (tmux -V to check) If you are using an older version than that, you're probably running an older Ubuntu and you should definitely consider pointing at a ppa with backports.
This definitely doesn't work with kitty, and is effectively "hardcoding" the terminal in terms of input, but it is better than hardcoding specific keys.
So I don't have enough points to comment,so I'll say it here instead. I believe the preferred solution is using
set -g default-terminal "screen-256color" in your ~/.tmux.conf. I actually had this problem a while ago and decided to go with sumanta's solution :
bind -n End send-key C-e
bind -n Home send-key C-a
However I had forgotten I left this in here and ended up having a similar issue with vim (home and end were copy pasting from registers) instead of zsh. In short bind DOES affect vim.
I wasted a lot of time trying all off the above.
In the end I reverted to barbarism:
sudo apt purge tmux
sudo apt install tmux
fixed it for me.
I see that $DISPLAY is set to localhost:0.0 if I am running over a vnc server this may not be correct, is there a way to automatically set it in my login script?
Here's something I've just knocked up. It inspects the environment of the last-launched "gnome-session" process (DISPLAY is set correctly when VNC launches a session/window manager). Replace "gnome-session" with the name of whatever process your VNC server launches on startup.
PID=`pgrep -n -u $USER gnome-session`
if [ -n "$PID" ]; then
export DISPLAY=`awk 'BEGIN{FS="="; RS="\0"} $1=="DISPLAY" {print $2; exit}' /proc/$PID/environ`
echo "DISPLAY set to $DISPLAY"
else
echo "Could not set DISPLAY"
fi
unset PID
You should just be able to drop that in your .bashrc file.
do you use Bash? Go to the file .bashrc in your home directory and set the variable, then export it.
DISPLAY=localhost:0.0 ; export DISPLAY
you can use /etc/bashrc if you want to do it for all the users.
You may also want to look in ~/.bash_profile and /etc/profile
EDIT:
function get_xserver ()
{
case $TERM in
xterm )
XSERVER=$(who am i | awk '{print $NF}' | tr -d ')''(' )
XSERVER=${XSERVER%%:*}
;;
aterm | rxvt)
;;
esac
}
if [ -z ${DISPLAY:=""} ]; then
get_xserver
if [[ -z ${XSERVER} || ${XSERVER} == $(hostname) || \
${XSERVER} == "unix" ]]; then
DISPLAY=":0.0" # Display on local host.
else
DISPLAY=${XSERVER}:0.0 # Display on remote host.
fi
fi
export DISPLAY
I'm guessing here, based on issues I've had in the past which I did solve:
you're connecting to a vnc server on machine B, displaying it using a VNC client on machine A
you're launching a console (xterm or equivalent) on machine B and using that to connect to machine C
you want to launch an X-based application on machine C, having it display to the VNC server on machine B, so you can see it on machine A.
I ended up with two solutions. My original solution was based on using rsh. Since then, most of our servers have had ssh installed, which has made this easier.
Using rsh, I put together a table of machines vs OS vs custom options which would guide this process in perl. Bourne shell wasn't sufficient, and we don't have bash on Sun or HP machines (and didn't have bash on AIX at the time - AIX 5L wasn't out yet). Korn shell wasn't much of an option, either, since most of our Linux boxes don't have pdksh installed. But, if you don't face these limitations, you can implement the idea in ksh or bash, I think.
Anyway, I would basically run 'rsh $machine -l $user "$cmd"' where $machine, of course, was the machine I was logging in to, $user, similarly obvious (though when I was going in as "root" this had some variance as we have multiple roots on some machines for reasons I don't fully understand), and $cmd was basically "DISPLAY=$DISPLAY xterm", though if I were launching konsole, for example, $cmd would be "konsole --display=$DISPLAY". Since $DISPLAY was being evaluated locally (where it's set properly), and not being passed literally across rsh, the display would always be set correctly.
I also had to make sure that no one did anything silly like reset DISPLAY if it was already set.
Now, I just use ssh, make sure that X11Forwarding is set to yes on the server (sshd_config), and then I can just ssh to the machine, let X commands go across the wire encrypted, and it'll always go back to the right place.
Your vncserver have a configuration file somewher that set the display number. To do it automaticaly, one solution is to parse this file, extract the number and set it correctly. A simpler (better) is to have this display number set in a config script and use it in both your VNC server config and in your init scripts.
You'll need to tell your vnc client to export the correct $DISPLAY once you have logged in. How you do that will probably depend on your vnc client.