Tmux is a great alternative to gnu screen. I can’t believe I’ve never posted my custom Tmux config for Cygwin after all the work I put into it years ago. So here it is. Its features include:
- Uses ctrl+a, like gnu screen, instead of ctrl+b
- Mouse interaction is enabled
- Tab bar/windows:
- Current tab is highlighted in cyan
- Cycle through tabbed windows with a click on its tab or ctrl+arrowkeys
- Reorder tabbed windows with a drag of its tab or alt+arrowkeys
- ctrl+a,/ to rename a tab on the tab bar
- Create new window with ctrl+a,c
- Panes
- Create split panes with vertical=ctrl+a,| and horizontal=ctrl+a,-
- Move around panes with click or ctrl+shift+arrowkeys
- Resize panes by dragging on the separator bar or use ctrl+shift+alt+arrowkeys
- Panes automatically resize to fit OS window
- Clipboard/highlighting
- Copy text to clipboard by highlighting it. Had to use a minor hack to fix a cygwin selection problem
- Paste from clipboard with right click
- Middle mouse button+drag starts copy mode
- When in copy mode, u runs the selection as a command in a separate window (Instead of “cygstart” for cygwin, use “xdg-open” for linux, or “open” for MacOS X)
- Double click selects word
- Double middle click runs the word under the mouse as a command
- Start the session on the current bash directory
- Escape time is lowered for quicker response to scroll buffer access (ctrl+a,pageup)
To use this, save the file to ~/.tmux.conf
#Set current directory setting for cygwin
set-environment -g CHERE_INVOKING 1
#Mouse interaction
set -g mouse on
#Lower escape timing from 500ms to 50ms for quicker response to scroll-buffer access
set -s escape-time 50
#Window always takes up largest possible max size
set-window-option -g aggressive-resize
#Highlight active window in tab-bar at bottom in cyan
set-window-option -g window-status-current-bg cyan
#Reorder windows in status bar by drag & drop
bind-key -n MouseDrag1Status swap-window -t=
#Copy to clipboard on text selection in cygwin. Move cursor position 1 to the right before copy to bypass a bug
bind -Tcopy-mode MouseDragEnd1Pane send-keys -X cursor-right\; send -X copy-selection-and-cancel\; run-shell -b "tmux show-buffer > /dev/clipboard"
#Paste from clipboard with right click in cygwin
bind-key -n MouseDown3Pane run-shell 'tmux set-buffer -b winclip "$(cat /dev/clipboard)"'\; paste-buffer -db winclip
#Middle drag starts copy mode
bind -n MouseDrag2Pane copy-mode -M
#When in copy mode, "u" runs the selection as a command in a separate window (Instead of "cygstart" for cygwin, use "xdg-open" for linux, or "open" for MacOS X)
bind -Tcopy-mode u send -X copy-selection-and-cancel\; run-shell -b "tmux show-buffer | xargs cygstart"
#Double click selects word
bind-key -n DoubleClick1Pane copy-mode -M\; send-keys -X select-word
#Double middle click runs the word under the mouse as a command. See description for MouseDown3Pane above
bind-key -n DoubleClick2Pane copy-mode -M\; send-keys -X select-word\; send -X copy-selection-and-cancel\; run-shell -b "tmux show-buffer | xargs cygstart"
#Remap prefix to Control+a
set -g prefix C-a
unbind C-b
#bind 'C-a C-a' to type 'C-a'
bind C-a send-prefix
#Start in CWD when creating or splitting tabs; move the splitting planes keys to | and -
bind '|' split-window -h -c '#{pane_current_path}' # Split panes horizontal
bind '-' split-window -v -c '#{pane_current_path}' # Split panes vertically
bind c new-window -c '#{pane_current_path}' # Create new window
unbind '"'
unbind %
#prefix, / -- Renames window, but starts blank
bind-key / command-prompt "rename-window '%%'"
#Select next/prev window with Ctrl+(Left|Right)
bind-key -n C-Right next-window
bind-key -n C-Left previous-window
#Reorder window with Alt+(Left|Right)
bind-key -n M-Left swap-window -t -1
bind-key -n M-Right swap-window -t +1
#Switch panes using Ctrl+Shift+arrow
bind -n C-S-Left select-pane -L
bind -n C-S-Right select-pane -R
bind -n C-S-Up select-pane -U
bind -n C-S-Down select-pane -D
#Resize panes using Ctrl+Shift+Alt+arrow
bind-key -n C-S-M-Up resize-pane -U 1
bind-key -n C-S-M-Down resize-pane -D 1
bind-key -n C-S-M-Left resize-pane -L 1
bind-key -n C-S-M-Right resize-pane -R 1
|
It’s a bit of a pain reading results from batch requests to Mailchimp. Here is a quick and dirty bash script to get and pretty print the JSON output. It could be cleaned up a little, including combining some of the commands, but meh.
#Example variables
BATCHID=abc1234567;
APIKEY=abcdefg-us11@us11.api.mailchimp.com;
APIURL=us11.api.mailchimp.com;
#Request the batch information from Mailchimp
curl --request GET --url "https://dummy:$APIKEY@$APIURL/3.0/batches/$BATCHID" 2> /dev/null | \
#Get the URL to the response
grep -oP '"response_body_url":"https:.*?"' | \
grep -oP 'https:[^"]*' | \
#Get the response
xargs wget -O - 2> /dev/null | \
#The response is a .tar.gz file with a single file in it. So get the contents of this file
tar -xzvO 2> /dev/null | \
#Pretty print the json of the full return and the “response” objects within
php -r '$Response=json_decode(file_get_contents("php://stdin"), true); foreach($Response as &$R) $R["response"]=json_decode($R["response"], true); print json_encode($Response, JSON_PRETTY_PRINT);'
|
#This script takes a newline delimited file list from STDIN for md5 hashing
#This script requires the `md5sum`, `pv`, `paste`, `bc`, and 'numfmt' commands
#The output of the md5s are stored in the file specified by the first parameter
#The format for each md5 hash to the output file is "$FileName\t$Hash\n"
#File sizes are always output in megabytes with 3 decimal places
#While calculating the hashes the script keeps the user informed of the progress of both the current file and all the files as follows:
#1) Before file starts: "Hashing: $FileName ($FileSize MiB)\n"
#2) During transfer: The progress of the hash of the current file ran through `pv`
#3) During transfer: The progress of the hashing of all the files, ran through `pv`
#4) After transfer: "Finished $TotalProgressPercent% ($ProcessedBytes/$TotalBytes MiB)\n\n"
#Get $Outfile from the first argument and the $FileList from STDIN (newline delimited)
OutFile="$1";
FileList=`cat /dev/stdin`
#Format a byte count in MegaBytes with comma grouping and 3 decimal places
MbFmtNoExt ()
{
echo "scale=3; $1/1024/1024" | bc | echo -n `xargs numfmt --grouping`
}
#Add " MiB" to the end of MbFmtNoExt
MbFmt ()
{
echo `MbFmtNoExt $1`" MiB"
}
#Calculate and output the total size of the file list
echo -n "Calculating total size: "
TotalSize=`echo "$FileList" | xargs -d"\n" stat --printf="%s\n" | paste -s -d+ | bc`
MbFmt $TotalSize
echo #Add an extra newline
#Create a fifo to keep track of the total complete
TotalDoneFifo=$(mktemp)
TotalDoneBG=0
rm "$TotalDoneFifo"
mkfifo "$TotalDoneFifo"
cat > "$TotalDoneFifo" & #Do not close read of fifo
Cleanup() {
rm "$TotalDoneFifo"
kill $TotalDoneBG
exit 0
}
trap Cleanup SIGTERM SIGINT
#Start the TOTAL line
tail -f "$TotalDoneFifo" | pv -s $TotalSize -F "%b %t %p %e" > /dev/null &
TotalDoneBG=$!
#Run over the list (newline delimited)
CalculatedBytes=0
IFS=$'\n'
for FileName in `echo "$FileList"`
do
#Output the file size and name to STDOUT
FileSize=`stat --printf="%s" "$FileName"`
echo "Hashing: $FileName ("`MbFmt $FileSize`")"
#Output the filename to $OutFile
echo -n $FileName$'\t' >> $OutFile
#Run the md5 calculation with `pv` progress
#Output the hash to $OutFile after the FileName and a tab
cat "$FileName" | pv -s $FileSize -c | tee -a "$TotalDoneFifo" | md5sum | awk '{print $1}' >> $OutFile
#Output the current progress for the entire file list
#Format: "Finished $TotalProgressPercent% ($ProcessedBytes/$TotalBytes MiB)\n\n"
CalculatedBytes=$(($CalculatedBytes+$FileSize))
echo -n "Finished "
printf "%.3f" `echo "scale=4; $CalculatedBytes*100/$TotalSize" | bc`
echo "% ("`MbFmtNoExt $CalculatedBytes`"/"`MbFmt $TotalSize`$')\n'
done
Cleanup
|
The following is a simple bash script to ping a different domain once a second and log the output. By default, it pings #.castledragmire.com, where # is an incrementing number starting from 0.
The script is written for Cygwin (See the PING_COMMAND variable at the top) but is very easily adaptable to Linux.
The log output is: EPOCH_TIMESTAMP DOMAIN PING_OUTPUT
#This uses Window's native ping since the Cygwin ping is sorely lacking in options
#"-n 1"=Only runs once, "-w 3000"=Timeout after 3 seconds
#The grep strings are also directly tailored for Window's native ping
PING_COMMAND=$(
echo 'C:/Windows/System32/PING.EXE -n 1 -w 3000 $DOMAIN |';
echo 'grep -iP "^(Request timed out|Reply from|Ping request could not find)"';
)
i=0 #The subdomain counter
STARTTIME=`date +%s.%N` #This holds the timestamp of the end of the previous loop
#Infinite loop
while true
do
#Get the domain to run. This requires a domain that has a wildcard as a primary subdomain
DOMAIN="$i.castledragmire.com"
#Output the time, domain name, and ping output
echo `date +%s` "$DOMAIN" $(eval $PING_COMMAND)
#If less than a second has passed, sleep up to 1 second
ENDTIME=`date +%s.%N`
SLEEPTIME=$(echo "1 - ($ENDTIME - $STARTTIME)" | bc)
STARTTIME=$ENDTIME
if [ $(echo "$SLEEPTIME>0" | bc) -eq 1 ]; then
sleep $SLEEPTIME
STARTTIME=$(echo "$STARTTIME + $SLEEPTIME" | bc)
fi
#Increment the subdomain counter
let i+=1
done
|