I want to duplicate my ssh session again.
For example, my window-name is "user#host'. I wish to press prefix key + S to do 'ssh user#host on a new window'
$ tmux bind S confirm-before "neww ssh #W"
After try this, it just issue a ssh command without the option 'user#host'
The tmux version is 1.8 on CentOS 7.
You can try something like this, though it is a little ugly. Place this into your tmux.conf:
bind S neww "$(ps -ao pid,tty,args | sort | awk '$1 ~ /#{pane_pid}/{VAR=$2} $2 ~ VAR && $3 ~ /ssh/{$1=\"\"; $2=\"\"; print}')"
Explanation
Creat a binding named S and have it open a new window, using the argument as the initial command
bind S neww "..."
Execute the output of the inner command
$(...)
List the pid, tty, and command (with arguments) of all processes
ps -ao pid,tty,args | ...
Sort by pid
... | sort | ...
Feed output into awk
... | awk '...'
Find tty of current pane/window, and place it in VAR (#{} is substituted by tmux)
$1 ~ /#{pane_pid}/{VAR=$2}
Find process that has the tty we found earlier AND has a command that starts with ssh. Note that we are assuming that the pid of the ssh session is greater than the shell it was invoked in. This should be true in most cases.
$2 ~ VAR && $3 ~ /ssh/{...}
Remove pid, tty, and print the remainder. This will be the ssh command with all arguments and options. This is the command that will get executed in a new window.
$1=\"\"; $2=\"\"; print
Related
compdef cmd1=service can be used to define a completion alias, however, that works only when the arguments are going to be the same.
For example, consider a helper script which rewrites some arguments before executing another command:
| What is typed | What is executed |
|---------------+----------------------------|
| s | systemctl |
| s q | systemctl status |
| s q foo | systemctl status foo |
| s j foo | journalctl --unit foo |
| s r foo | sudo systemctl restart foo |
We can ask the script to print the arguments it would execute, so e.g. PRINT_ONLY=1 s would print just systemctl.
Assuming completion is already set up for systemctl / journalctl / sudo, how would one define a zsh completion for such a script? Rather than redundantly reimplementing completion for those commands, how to implement completion for s such that the completion system is invoked with a transformed command -- i.e. something like function _s() { get_completions $(PRINT_ONLY=1 s "$#") ; }?
This should go in a file named _s somewhere on your $fpath:
#compdef s
local -a orig_command new_words
orig_command=("${words[#]}")
if [[ $words[-1] == '' ]]; then
# remove an empty word at the end, which the completion system cares about
orig_command[-1]=()
fi
# split the rewritten command into words using the shell parser
new_words=("${(z)$(PRINT_ONLY=1 "${orig_command[#]}")}")
if [[ $words[-1] == '' ]]; then
# restore the empty word if we removed it
new_words+=('')
fi
# update the cursor position
CURRENT=$(( CURRENT - $#words + $#new_words ))
words=("${new_words[#]}")
# restart completion with the rewritten command
_normal
Note: this doesn't do any error handling and just assumes that any unknown arguments will be passed to the default command (e.g. s start foo -> systemctl start foo). If that's not the case, let me know how s behaves in those cases and I can update the completion script.
When using tmux, I generally have an editor open in a split on top, and a shell at the bottom. Right now, I'm writing a python script, and on the bottom half of the split I can't find a way to toggle back and forth between ipython and bash: the best I can do is create a nested split between those two, sharing the bottom half of the screen. Right now this looks something like the following.
Is there something like tabs within a pane, so I can switch back and forth between bash/ipython while keeping the editor locked/frozen in place at the top? It's not ideal right now to have to choose between switching to a new tab for one of the shell prompts or using these tiny splits. Tmux is so flexible it seems like there'd be a way to do this straightforward pane-lock. Thanks
Resolved using nested tmux sessions. I based my solution on a much-stripped down version of nested-tmux. I launch a nested session and then use tabs within that nested session. To launch a nested session, I use the following script tmux-nested.sh (adapted from the nested-tmux repo):
#!/bin/sh
TMUX_PARENT=$(basename "$TMUX")
TMUX_PARENT="${TMUX_PARENT%%,*}"
export TMUX_PARENT
_SOCK="r$RANDOM"
tmux -L "$_SOCK" new-session -s "$_SOCK"
This creates a nested session with socket given a random filename (a hardcoded value wouldn't permit multiple nested sessions, say in different tabs in the parent session).
In my .tmux.conf file, I add the following line on startup to change the tmux prefix for nested sessions:
# nested session logic
if-shell '! [ -z "$TMUX_PARENT" ]' 'set-option -g prefix C-b'
(where my normal prefix is a backtick)
EDIT:
I expanded this function into a much more robust implementation, which can be found below:
# Nest tmux sessions
tmux_nested() {
local usagestring='usage: tmux-nested [-n | -a nested-session-# | -l]'
if [[ -z $TMUX ]]; then
# ensure invoked within active session
echo "'tmux_nested' should be invoked inside an active tmux session"
return 1
fi
# read flags and check for number of existing nested sessions
local nested session_name
nested=$(tmux list-sessions -F '#{session_name}' | \
ggrep -P '^nested[\d]+' --color=never | sort -V)
while getopts ':lna:' opt; do
case $opt in
l)
[[ -z $nested ]] && nested="No nested sessions running"
echo "$nested" && return 0;;
n)
# if new session requested: create, set <C-b> tmux prefix, and attach
for (( i = 1;; i++ )); do
# get lowest available numeric value for new session name
if ! tmux has-session -t "nested$i" 2> /dev/null; then
session_name="nested$i" && break
fi
done
tmux new-session -ds "$session_name"
tmux send-keys -t "$session_name" \
"tmux set prefix C-b" ENTER "clear" ENTER
env TMUX='' tmux attach -t "$session_name"
return $?;;
a)
# attach to specified session if requested
session_name="nested${OPTARG}"
if ! env TMUX='' tmux attach -t "$session_name"; then
echo "Try 'tmux_nested -l'?" && return 1
fi;;
*) echo "$usagestring" && return 1;;
esac
done
# incorrect invocation, report incorrect invocation and exit
echo "$usagestring" && return 1
}
I am running a lot of tmux session like
Each tmux session is started as:
today=`date +%Y-%m-%d-%H_%M_%S_%N`
tmux new-session -d -s "$today" zsh /home/path/to/script.sh "with_params"
If i want to only view the list of tmux sessions. I can do by
tmux ls | awk '{print $1}';
Now what i want is to monitor their output using the while loop to show the session name and the recent output:
while true;
do;
echo "##########################################"
??? For list of tmux session; do
sleep 1;
??? session name
??? recent last 5 lines of output
done
echo "##########################################"
done;
??? : What commands should i use
You can use capture-pane to show the last five lines of output:
tmux capture-pane -p -S- -E-|sed '/^$/d'|tail -5
Add -t to specify the pane you want to see - if you just give a session it will use the active pane in the current window.
Add -e if you want colour sequences included.
here is my simple command.
ls -lrth ../ | grep file | awk -F" " -v orig=`cd .. | pwd ` -v sort=`pwd` '{print $NF "," $7"/"$8"/"$9","orig"," sort }'
I'm trying to get the value of my previous path just above my current working directory.
current working directory = /home/PC1/Environment/Test1
what i want to get the value of pwd is /home/PC1/Environment and not want to hardcode it.
i tried to use cd .. | pwd but it still displays my current working directory not my previous working directory
can anyone help? some suggestions would be nice.
Use $(cd .. && pwd). You can also use $(cd - && pwd) to get your previous working directory even if it wasn't the parent of your current one. (In general, you should use $(...) instead of `...` to get command output; the latter interferes with quoting and doesn't nest, so can cause surprising results).
Your cd | pwd runs the cd and the pwd at the same time in different subshells, which is not what you want.
I know there is $USER, $HOME, $PATH, etc.
There are plenty: DBUS_SESSION_BUS_ADDRESS, XAUTHORITY, GDM_LANG, etc. You can view all your environment variables with the env command - type it in inside a terminal.
As far as I know, there's no limitations on environment variables, they can be of any length, and anything can create them and add them to the environment (using export, as you may have seen). Conceptually, environment variables act as "global variables" that are shared among all programs running in a terminal.
Err... lots?
$ env | cut -d = -f 1 | sort | uniq
_
COLORFGBG
DBUS_SESSION_BUS_ADDRESS
DESKTOP_SESSION
DISPLAY
DM_CONTROL
EDITOR
GPG_AGENT_INFO
GS_LIB
GTK2_RC_FILES
GTK_RC_FILES
HISTCONTROL
HOME
KDE_FULL_SESSION
KDE_MULTIHEAD
KDE_SESSION_UID
KDE_SESSION_VERSION
KONSOLE_DBUS_SERVICE
KONSOLE_DBUS_SESSION
LANG
LANGUAGE
LESSCLOSE
LESSOPEN
LIBGL_DRIVERS_PATH
LOGNAME
LS_COLORS
OLDPWD
PATH
PROFILEHOME
PWD
QT_PLUGIN_PATH
SESSION_MANAGER
SHELL
SHLVL
SSH_AGENT_PID
SSH_AUTH_SOCK
TERM
USER
WINDOWID
WINDOWPATH
XCURSOR_THEME
XDG_DATA_DIRS
XDG_SESSION_COOKIE
XDM_MANAGED
Yep, $SHELL is one of them that I know of.
Edit: see this page for more of them.
How about $DISPLAY and $LD_LIBRARY_PATH.
Every system is configured differently so rather than listing them all here, just enter the following command to list them all on your own system:
set | sed 's/=.*//' | grep -v "^[A-Z_]\{4\}$"
I'd use set instead of env as it has greater scope. Most system environment variables are in upper case so to add that restriction add an extra grep to the pipe line.
set | sed 's/=.*//' | grep "[A-Z_]" | grep -v "^[A-Z_]\{4\}$"
env | cut -d = -f 1 | grep -E "([A-Z_]{4,})"
Use this command
$LD_LIBRARY_PATH and $LD_PRELOAD both exist for linking.
User defined environment variables don't have to four characters long (ex. CLASSPATH)