tmux bind % and " within tmux.conf - config

I try to map the % and " key to a new command without success.
What I tried so far are these options:
bind \% split-window -h
and
bind % split-window -h
which results in an error for \% with .tmux.conf:143: unknown key: \%
both are not working.
The reason I want to remap:
I want to highlight the active pane background.
I already did it for switching pane with these options, but in splitting the color obviously is not updated.
example for switching panes:
bind h select-pane -P 'bg=default' \; select-pane -L \; select-pane -P 'bg=black'
bind j select-pane -P 'bg=default' \; select-pane -D \; select-pane -P 'bg=black'
bind k select-pane -P 'bg=default' \; select-pane -U \; select-pane -P 'bg=black'
bind l select-pane -P 'bg=default' \; select-pane -R \; select-pane -P 'bg=black'
BTW: i have tmux version 2.6

You should not have a problem with your 2nd line, and for " you need to quote it. Eg this works for me in 2.6:
bind-key '"' split-window \; send-keys "pwd" Enter
bind-key % split-window -h \; send-keys "pwd" Enter

Related

find: missing argument to `-exec' in SSH command

I'm using SSH inside a CI/CD Pipeline (so it's non-interactive), and trying to execute a couple find command (among others) to change the ownership of files and directories after executing LFTP mirror, but I keep getting this error (which makes the whole Pipeline fail):
find: missing argument to `-exec'
This is the command that uses find:
ssh -i ~/.ssh/id_rsa $USERNAME#$HOST "[other commands...]; find $SOME_PATH/ -type d -exec 'chmod 755 {} \;' && find $SOME_PATH/ -type f -exec 'chmod 644 {} \;' && echo Done"
I've already tried using escaped double quotes like so: -exec \"chmod 755 {} \;\" - but keeps throwing the same error.
What would be the main issue here?
EDIT: Solved. I removed any quotes for the -exec, removed the && and append an extra semicolon ; to each find and it works as expected.
ssh -i ~/.ssh/id_rsa $USERNAME#$HOST "[other commands...]; find $SOME_PATH/ -type d -exec chmod 755 {} \;; find $SOME_PATH/ -type f -exec chmod 644 {} \;; echo Done"
So use -exec whatever-command {} \;; [other command, echo, find, ls, whatever...].
Please check this answer for more information: https://unix.stackexchange.com/a/139800/291364
[...] When find sees that spurious exit after the -exec … ; directive, it doesn't know what to do with it; it hazards a (wrong) guess that you meant it to be a path to traverse. You need a command separator: put another ; after \; (with or without a space before). [...]
\; is processed to ; locally before the string is passed to the remote shell. You need to escape the backslash so the the ; remains escaped on the remote end.
ssh -i ~/.ssh/id_rsa $USERNAME#$HOST \
"[other commands...]; find $SOME_PATH/ -type d -exec 'chmod 755 {} \\;'
&& find $SOME_PATH/ -type f -exec 'chmod 644 {} \\;' && echo Done"
A better idea would be to use single quotes for the command argument and pass the value of $SOME_PATH as an argument to a shell.
ssh -i ~/.ssh/id_rsa $USERNAME#$HOST \
sh -c '...;
find "$1" -type d -exec chmod 755 {} \; &&
find "$1" -type f -exec chmod 644 {} \; &&
echo Done' _ "$SOME_PATH"
Note that chmod and its arguments each need to be separate arguments to the find.
In fact, you don't need to run find twice; you can provide two -exec primaries, each paired to a different -type:
ssh -i ~/.ssh/id_rsa $USERNAME#$HOST \
sh -c '...;
find "$1" \( -type d -exec chmod 755 {} \; \) -o
\( -type f -exec chmod 644 {} \; \)
&& echo Done' _ "$SOME_PATH"
Rather than the complex find commands (and associated quoting/escaping mess), you can use the built-in capabilities of chmod sympolic modes to set the permissions on files and directores differently. Specifically, the "X" permission means essentially "execute if it makes sense", which mostly means directories rather than files. The main exception is that if there's a file that already has execute set, it assumes it's intentional and keeps it. If that's ok, you can use this simpler command:
chmod -R u=rwX,go=rX "$1" # Set non-executable files to 644, executables and directories to 755
If you need to specifically clear execute bits on files, or just want to stick with find, another option take advantage of the fact that chmod accepts multiple arguments to use find ... -exec ... {} + instead of the \; version. "+" isn't a shell metacharacter, so it doesn't reqire special treatment:
find $SOME_PATH/ -type d -exec chmod 755 {} + ; find $SOME_PATH/ -type f -exec chmod 644 {} +

Delete keys with spaces

I am trying to delete multiple keys from my remote Redis db using the following command.
redis-cli -h <host> -p 6379 KEYS "myprefix:*" | xargs redis-cli -h <host> -p 6379 DEL
It has deleted all the matching keys except the ones having spaces in them.
For e.g.
Deleted:
myprefix:abc
myprefix:def
myprefix:ghi
Not deleted:
myprefix:jkl mno
myprefix:pqr stu
myprefix:vwx yza
What should be my query pattern so that these get deleted too? I tried googling but was unable to find any solution.
The issue is with xargs, not your KEYS query. If you run your query, you will notice that it correctly returns the keys with spaces in them. The problem is that by default xargs splits the strings piped into it by blanks and newlines. To change this behaviour so that it only delimits by newlines, add the -d "\n" option. For example:
redis-cli -h <host> -p 6379 keys "myprefix:*" | xargs -d "\n" redis-cli -h <host> -p 6379 del
For anyone using Mac OS xargs (BSD) instead of linux (GNU) xargs the following works
redis-cli -h <host> -p 6379 keys "myprefix:*" | xargs -I% redis-cli -h <host> -p 6379 del %
or for other weird characters like speech marks this works
redis-cli -h <host> -p 6379 --scan --pattern "myprefix:*" | tr '\n' '\0' | xargs -0 -I% redis-cli -h <host> -p 6379 del %
Here is an another hack to make it work on Mac.
redis-cli KEYS 'pattern*' | xargs -0 -n1 'echo' | sed "s/^/'/g" | sed "s/$/'/g" | xargs redis-cli DEL
This basically puts quote around your keys before passing to redis-cli DEL

How can I send password safely to tmux?

The following is my code in create_tmux.zsh
#!/bin/zsh
SESSIONNAME=$1
echo $SESSIONNAME
tmux has-session -t $SESSIONNAME &> /dev/null
if [ $? != 0 ]
then
tmux new-session -d -s $SESSIONNAME -n emacs
tmux new-window -t $SESSIONNAME:1 -n a
tmux send-keys -t $SESSIONNAME:1 'ssh -Y a#bc.com;$2' C-m
fi
tmux attach -t $SESSIONNAME
It's simple if I run
create_tmux.zsh ab $%^^&av1#
But in this way, it not only shows in the terminal of my password but also recorded in history.
How can I solve this?
Thank you

find and replace with variables

I'm trying to find and replace with variables, but it doesn't work.
Here is the code. I need to append -C -w 10% -c 5% -p /u0 to append to the end of a matching line. I do not know how to suppress the (-) Any ideas? Thank you.
OLD=$(command[check_disk]=/usr/local/nagios/libexec/check_disk -w 10% -c 5% -p / -p /var -p /tmp -p /home -p /boot -p /usr -A -e)
NEW=$(command[check_disk]=/usr/local/nagios/libexec/check_disk -w 10% -c 5% -p / -p /var -p /tmp -p /home -p /boot -p /usr -A -e -C -w 10% -c 5% -p /u0)
sed -i "s/$OLD/$NEW/" /home/scripts/nrpe.cfg
Try this (assumes bash):
OLD='command[check_disk]=/usr/local/nagios/libexec/check_disk -w 10% -c 5% -p / -p /var -p /tmp -p /home -p /boot -p /usr -A -e'
NEW='command[check_disk]=/usr/local/nagios/libexec/check_disk -w 10% -c 5% -p / -p /var -p /tmp -p /home -p /boot -p /usr -A -e -C -w 10% -c 5% -p /u0'
oldEscaped=$(sed 's/[^^]/[&]/g; s/\^/\\^/g' <<<"$OLD")
newEscaped=$(sed 's/[\\&/]/\\&/g' <<<"$NEW")
sed -i "s/$oldEscaped/$newEscaped/" /home/scripts/nrpe.cfg
Your first problem was that you mistook $(...) for a string-quoting mechanism (it is not; it's used for command substitution (executing the enclosed command and replacing the construct with the command's output)).
To assign literal strings, simply use single quotes as above.
Your second problem was that you can't blindly pass strings to sed's s (string-substitution) command, because certain characters have special meaning to sed, so to use them literally they have to be escaped - the most obvious problem being the / instances in the strings, which get mistaken for the delimiters of the s/.../.../ command.
Therefore, 2 auxiliary sed commands are used to perform the requisite escaping:
sed 's/[^^]/[&]/g; s/\^/\\^/g' <<<"$OLD" escapes the old string so that none of its characters can be mistaken for the regex delimiter or special regular-expression characters.
sed 's/[\\&/]/\\&/g' <<<"$NEW" escapes the new string so that none of its characters can be mistaken for the regex delimiter or backreferences (such as &, or \1).
Finally, note that it's better not to use all-uppercase shell variable names such as $OLD, so as to avoid conflicts with environment variables.

ssh on remote server to kill process, pushd script folder and execute the script is not wor

I have a requirement to kill remote process of specific patter, pushd the path to startup and execute the script.
I tried so far with
pid=$(ssh -q username#virt ps -ef|grep $APP|grep $PORT|awk '{print $2}')
ssh -q username#virt kill -9 $pid
ssh -q username#virt "find /shared/local/path1/app -name "start_app*" -exec grep -nl "9122" {} \;| xargs -0 -I '{}' bash -c 'pushd $(dirname {});bash {};'"
When I execute above command kill processing is working fine. The final step to find for scriptfile and execute script by pushing the folder to the path is not working.
For some reason the pushd is not working fine.
The command on the local server do work fie with
find /shared/local/path1/app -name "start_app*" -exec grep -nl "9122" {} \;| xarg -0 -I '{}' bash -c 'pushd $(dirname {});bash {};'
Please help a more effective solution to accomplish this task.
You have an error in the quotes here:
ssh -q username#virt "find /shared/local/path1/app -name "start_app*" -exec grep -nl "9122" {} \;| xargs -0 -I '{}' bash -c 'pushd $(dirname {});bash {};'"
Try this in stead:
ssh -q username#virt "find /shared/local/path1/app -name 'start_app*' -exec grep -nl '9122' {} \;| xargs -0 -I '{}' bash -c 'pushd \$(dirname {});bash {};'"