-# History related options first, or else
-# we risk screwing up history history. And this is duplicated
-# in ~/.bash_profile just for good measure
-# history number. History expansion is good.
-PS4='$LINENO+ '
-# history file size limit, set to unlimited.
+# History related options first and always, or else we risk screwing up
+# the history file. This is duplicated in ~/.bash_profile just for good
+# measure
+
+# History file size limit, set to unlimited.
# this needs to be different from the default because
# default HISTFILESIZE is 500 and could clobber our history
HISTFILESIZE=
HISTTIMEFORMAT="%Y-%m-%d %I:%M %p "
# consecutive duplicate lines dont go in history
HISTCONTROL=ignoredups
-# works in addition to HISTCONTROL to do more flexible things
+# This works in addition to HISTCONTROL to do more flexible things
# it could also do the same things as HISTCONTROL and thus replace it,
# but meh. dunno why, but just " *" does glob expansion, so use [ ] to avoid it.
HISTIGNORE='pass *:[ ]*:otp *:oathtool *'
-# see comments in brc2 sl() function for background.
+#### begin section that works with sl() function to return from
+#### noninteractive ssh shells
if [[ $SSH_CONNECTION ]] \
&& [[ $BRC != t ]]; then
+ # Here we did not opt-in to running our .bashrc file so we just
+ # return, but we still setup a function to source it without returning
+ # so if we want it we don't have to restart our ssh connection.
brc() {
export BRC=t
source ~/.bashrc
return 0
else
- # the distinction between login and non-login shells is lame,
- # get rid of it. note ssh shells normally its login if a command is passed
+ ###### Begin sourcing of files #####
+
+ # The distinction between login and non-login shells is super lame
+ # and pretty random. get rid of that distinction.
if ! shopt -q login_shell; then
if [[ -r /etc/profile ]]; then
source /etc/profile
# this file, and we don't want to do that and cause an infinite
# loop.
fi
+
+ # source brc and brc2 if they exist. We have to readlink because we
+ # could be using sl() from ./brc.
_tmp=$(readlink -f ${BASH_SOURCE[0]})
_tmp=${_tmp%/*}
_tmp2=$_tmp/brc
source $_tmp2
fi
fi
+ ###### End sourcing of files #####
fi
+#### end section that works with sl() function to return from
+#### noninteractive ssh shells
# ensure no bad programs appending to this file will have an affect
# setting this also sets dotglob.
export GLOBIGNORE="*/.:*/.."
+# Useful info. see man bash.
+PS4='$LINENO+ '
+
+
# broken with bash_completion package. Saw a bug for this once. dont anymore.
# still broken in wheezy
# still buggered in latest stable from the web, version 2.1
export NNN_COLORS=2136
+export SL_FILES_DIR=/b/ds/sl/.iank
+export SL_INFO_DIR=/p/sshinfo
+
+
# * include files
}
+# sl: ssh, but firsh rsync our bashrc and related files to a special
+# directory on the remote host if needed.
+
+# Some environment variables and files need to be setup for this to work
+# (mine are set at the beginning of this file)
+
+# SL_FILES_DIR: Environment variable. Path to folder which should at
+# least have a .bashrc file or symlink. This dir will be rsynced to
+# remote hosts unless the host already has a $SL_FILES_DIR/.bashrc. In
+# that case, we assume it is a host you control and sync files to
+# separately and already has the ~/.bashrc you want. Symlinks in this
+# dir will be resolved. The directory name is important, it will be
+# created on the remote host under /root. The remote bash will also take
+# its .inputrc config from this folder (default of not existing is
+# fine). Mine looks like this:
+# https://iankelling.org/git/?p=distro-setup;a=tree;f=sl/.iank
+
+# SL_INFO_DIR: Environment variable. This folder stores info about what
+# we detected on the remote system and when we last synced. We expect it
+# to exist ahead of time. Sometimes you may want to forget about a
+# remote system, you can use sl --rsync, or the function for that slr
+# below.
+
+# For when ~/.bashrc is already customized on the remote server, you
+# might find it problematic that ~/.bashrc is sourced for ALL ssh
+# commands, even in scripts. This paragraph is all about that. bash
+# scripts dont source ~/.bashrc, but call ssh in scripts and you get
+# ~/.bashrc. You dont want this. .bashrc is meant for interactive shells
+# and if you customize it, probably has bugs from time to time. This is
+# bad. Here's how I fix it. I have a special condition to "return" in my
+# .bashrc for noninteractive ssh shells (you can copy this). To make
+# this work, you need to alter AcceptEnv in /etc/ssh/sshd_config, adding
+# the var BRC to it. And in ~/.ssh/config or equivalent, add SendEnv
+# BRC, plus any other environment vars you want to send. This function
+# uses the BRC environment variable to enable that. Also, I don't keep
+# most of my bashrc in .bashrc, because even though I return, the whole
+# file gets parsed which can fail if there is a syntax error (plus,
+# faster bash startup when we are just going to return).
+#
+sl() {
+ # Background on BRC var (no need to read if you just want to use this
+ # function): bash builtin vars and env show no difference in ssh vs
+ # local, except shell level which is not reliable. only reliable way I
+ # found was env var. env variables sent across ssh are strictly
+ # limited. We could override an obscure unused LC_var, like telephone,
+ # but I don't want to run into some edge case where that messes things
+ # up. Note, on hosts we dont control I start an inner shell with BRC
+ # set, and the inner shell also allows running a nondefault
+ # .bashrc. This means the outer shell still ran the default .bashrc,
+ # but that is the best we can do.
+
+ local now args remote dorsync haveinfo tmpa sshinfo tmp tmp2 type info_sec force_rsync sync_dirname
+ declare -a args tmpa
+
+ sync_dirname=${SL_FILES_DIR##*/}
+
+ now=$(date +%s)
+
+ # ssh [-1246Antivivisectionist] [-b bind_address] [-c cipher_spec] [-D [bind_address:]port]
+ # [-E log_file] [-e escape_char] [-F configfile] [-I pkcs11] [-i identity_file] [-L address]
+ # [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port] [-Q query_option]
+ # [-R address] [-S ctl_path] [-W host:port] [-w local_tun[:remote_tun]] [user@]hostname
+ # [command]
+
+ # ssh [-46AaCfGgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec]
+ # [-D [bind_address:]port] [-E log_file] [-e escape_char]
+ # [-F configfile] [-I pkcs11] [-i identity_file]
+ # [-J [user@]host[:port]] [-L address] [-l login_name] [-m mac_spec]
+ # [-O ctl_cmd] [-o option] [-p port] [-Q query_option] [-R address]
+ # [-S ctl_path] [-W host:port] [-w local_tun[:remote_tun]]
+
+ force_rsync=false
+ if [[ $1 == --rsync ]]; then
+ force_rsync=true
+ shift
+ fi
+
+ while [[ $1 ]]; do
+ case "$1" in
+ # note we dont support things like -4oOption
+ -[46AaCfGgKkMNnqsTtVvXxYy]*)
+ args+=("$1"); shift
+ ;;
+ -[bcDEeFIiJLlmOopQRSWw]*)
+ # -oOption etc is valid
+ if (( ${#1} >= 3 )); then
+ args+=("$1"); shift
+ else
+ args+=("$1" "$2"); shift 2
+ fi
+ ;;
+ *)
+ break
+ ;;
+ esac
+ done
+ remote="$1"; shift
+ if [[ ! $remote ]]; then
+ echo $0: error hostname required >&2
+ return 1
+ fi
+
+ dorsync=false
+ haveinfo=false
+ tmpa=($SL_INFO_DIR/???????????"$remote")
+ sshinfo=${tmpa[0]}
+ if [[ -e $sshinfo ]]; then
+ if $force_rsync; then
+ rm -f $sshinfo
+ else
+ haveinfo=true
+ fi
+ fi
+ if $haveinfo; then
+ tmp=${sshinfo[0]##*/}
+ tmp2=${tmp::11}
+ type=${tmp2: -1}
+ if [[ $type == b ]]; then
+ info_sec=${tmp::10}
+ for f in $SL_FILES_DIR/*; do
+ if (( $(stat -L -c%Y $f) > info_sec )); then
+ dorsync=true
+ rm -f $sshinfo
+ break
+ fi
+ done
+ fi
+ else
+ # use this weird yes thing to ensure we know ssh succeeded
+ if ! tmp=$(command ssh "${args[@]}" "$remote" "if test -e $SL_FILES_DIR/.bashrc -a -L .bashrc; then echo yes; fi"); then
+ echo failed sl test. doing plain ssh -v
+ command ssh -v "${args[@]}" "$remote"
+ fi
+ if [[ $tmp == yes ]]; then
+ type=a
+ else
+ dorsync=true
+ type=b
+ fi
+ fi
+ if $dorsync; then
+ RSYNC_RSH="ssh ${args[*]}" rsync -rptL $SL_FILES_DIR "$remote":
+ fi
+ if $dorsync || ! $haveinfo; then
+ sshinfo=$SL_INFO_DIR/$now$type"$remote"
+ touch $sshinfo
+ chmod 666 $sshinfo
+ fi
+ if [[ $type == b ]]; then
+ if (( ${#@} )); then
+ # Theres a couple ways to pass arguments, im not sure whats best,
+ # but relying on bash 4.4+ escape quoting seems most reliable.
+ command ssh "${args[@]}" "$remote" \
+ BRC=t bash -c '.\ '$sync_dirname'/.bashrc\;"\"\$@\""' bash ${@@Q}
+ elif [[ ! -t 0 ]]; then
+ # This case is when commands are being piped to ssh.
+ # Normally, no bashrc gets sourced.
+ # But, since we are doing all this, lets source it because we can.
+ cat <(echo . $sync_dirname/.bashrc) - | command ssh "${args[@]}" "$remote" BRC=t bash
+ else
+ command ssh -t "${args[@]}" "$remote" BRC=t INPUTRC=$sync_dirname/.inputrc bash --rcfile $sync_dirname/.bashrc
+ fi
+ else
+ if [[ -t 0 ]]; then
+ BRC=t command ssh "${args[@]}" "$remote" ${@@Q}
+ else
+ command ssh "${args[@]}" "$remote" BRC=t bash
+ fi
+ fi
+ # this function inspired from https://github.com/Russell91/sshrc
+}
+slr() {
+ sl --rsync "$@"
+}
+sss() { # ssh solo
+ sl -oControlMaster=no -oControlPath=/ "$@"
+}
+# kill off old shared socket then ssh
+ssk() {
+ m ssh -O exit "$@" || [[ $? == 255 ]]
+ m sl "$@"
+}
+# plain ssh
+ssh() {
+ BRC=t command ssh "$@"
+}
+
+
slog() {
# log with script. timing is $1.t and script is $1.s
# -l to save to ~/typescripts/
export WCDHOME=/a
+
# * include files
# generated instead of dynamic for the benefit of shellcheck
sudo systemctl suspend
}
-# ssh, copy my universal config over if needed.
-
-# By default .bashrc is sourced for ALL ssh commands. This is wonky.
-# Normally, this file is not sourced when a script is run, but we can
-# override that by sourcing ~/.bashrc. I want the same thing for ssh
-# commands. when a local script runs an ssh command, bashrc should not be
-# sourced, unless we use a modified command.
-#
-# So, in my bashrc, test for conditions of noninteractive ssh and return
-# if so. And we don't keep the rest of the code in .bashrc, because
-# even though we return, we parse the whole file which can cause errors
-# as we develop it.
-#
-# To test for an overriding condition: bash builtin vars and env show no
-# difference in ssh vs local, except shell level which is not
-# reliable. one option is to use an environment variable. env variables
-# sent across ssh are strictly limited. We could override an obscure
-# unused LC_var, like telephone, but I don't want to run into some edge
-# case where that messes things up. I choose to set SendEnv and
-# AcceptEnv ssh config vars to allow the environment variable BRC to
-# propagate across ssh, and for hosts I don't control, I start an inner
-# shell with it set, which doubles up as a way to have a nondefault
-# bashrc.
-sl() {
- # inspired from https://github.com/Russell91/sshrc
-
-
- local now args remote dorsync haveinfo tmpa sshinfo tmp tmp2 type info_sec force_rsync \
- sshinfo_dir sync_files_dir sync_files_dir
- declare -a args tmpa
- # This folder stores info about what we detected or synced. We expect it to exist
- # ahead of time. Change it for your own system.
- sshinfo_dir=/p/sshinfo
-
- # This folder should contain files or symlinks to all files that
- # should be rsynced to unknown hosts. The directory name is important,
- # it will be created on the remote host under /root. symlinks will be
- # resolved. It is expected to contain at least a .bashrc file or
- # symlink.
- sync_files_dir=/b/ds/sl/.iank
- sync_dirname=${sync_files_dir##*/}
-
- now=$(date +%s)
-
- # ssh [-1246Antivivisectionist] [-b bind_address] [-c cipher_spec] [-D [bind_address:]port]
- # [-E log_file] [-e escape_char] [-F configfile] [-I pkcs11] [-i identity_file] [-L address]
- # [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port] [-Q query_option]
- # [-R address] [-S ctl_path] [-W host:port] [-w local_tun[:remote_tun]] [user@]hostname
- # [command]
-
- # ssh [-46AaCfGgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec]
- # [-D [bind_address:]port] [-E log_file] [-e escape_char]
- # [-F configfile] [-I pkcs11] [-i identity_file]
- # [-J [user@]host[:port]] [-L address] [-l login_name] [-m mac_spec]
- # [-O ctl_cmd] [-o option] [-p port] [-Q query_option] [-R address]
- # [-S ctl_path] [-W host:port] [-w local_tun[:remote_tun]]
-
- force_rsync=false
- if [[ $1 == --rsync ]]; then
- force_rsync=true
- shift
- fi
-
- while [[ $1 ]]; do
- case "$1" in
- # note we dont support things like -4oOption
- -[46AaCfGgKkMNnqsTtVvXxYy]*)
- args+=("$1"); shift
- ;;
- -[bcDEeFIiJLlmOopQRSWw]*)
- # -oOption etc is valid
- if (( ${#1} >= 3 )); then
- args+=("$1"); shift
- else
- args+=("$1" "$2"); shift 2
- fi
- ;;
- *)
- break
- ;;
- esac
- done
- remote="$1"; shift
- if [[ ! $remote ]]; then
- echo $0: error hostname required >&2
- return 1
- fi
- dorsync=false
- haveinfo=false
-
- tmpa=($sshinfo_dir/???????????"$remote")
- sshinfo=${tmpa[0]}
- if [[ -e $sshinfo ]]; then
- if $force_rsync; then
- rm -f $sshinfo
- else
- haveinfo=true
- fi
- fi
- if $haveinfo; then
- tmp=${sshinfo[0]##*/}
- tmp2=${tmp::11}
- type=${tmp2: -1}
- if [[ $type == b ]]; then
- info_sec=${tmp::10}
- for f in $sync_files_dir/*; do
- if (( $(stat -L -c%Y $f) > info_sec )); then
- dorsync=true
- rm -f $sshinfo
- break
- fi
- done
- fi
- else
- # use this weird yes thing to ensure we know ssh succeeded
- if ! tmp=$(command ssh "${args[@]}" "$remote" "if test -e $sync_files_dir/.bashrc -a -L .bashrc; then echo yes; fi"); then
- echo failed sl test. doing plain ssh -v
- command ssh -v "${args[@]}" "$remote"
- fi
- if [[ $tmp == yes ]]; then
- type=a
- else
- dorsync=true
- type=b
- fi
- fi
- if $dorsync; then
- RSYNC_RSH="ssh ${args[*]}" rsync -rptL $sync_files_dir "$remote":
- fi
- if $dorsync || ! $haveinfo; then
- sshinfo=$sshinfo_dir/$now$type"$remote"
- touch $sshinfo
- chmod 666 $sshinfo
- fi
- if [[ $type == b ]]; then
- if (( ${#@} )); then
-
- # Theres a couple ways to do this. im not sure whats best,
- # but relying on bash 4.4+ escape quoting seems most reliable.
- command ssh "${args[@]}" "$remote" \
- BRC=t bash -c '.\ '$sync_dirname'/.bashrc\;"\"\$@\""' bash ${@@Q}
- elif [[ ! -t 0 ]]; then
- # This case is when commands are being piped to ssh.
- # Normally, no bashrc gets sourced.
- # But, since we are doing all this, lets source it because we can.
- cat <(echo . $sync_dirname/.bashrc) - | command ssh "${args[@]}" "$remote" BRC=t bash
- else
- command ssh -t "${args[@]}" "$remote" BRC=t INPUTRC=$sync_dirname/.inputrc bash --rcfile $sync_dirname/.bashrc
- fi
- else
- if [[ -t 0 ]]; then
- BRC=t command ssh "${args[@]}" "$remote" ${@@Q}
- else
- command ssh "${args[@]}" "$remote" BRC=t bash
- fi
- fi
-}
-slr() {
- sl --rsync "$@"
-}
-sss() { # ssh solo
- sl -oControlMaster=no -oControlPath=/ "$@"
-}
-# kill off old shared socket then ssh
-ssk() {
- m ssh -O exit "$@" || [[ $? == 255 ]]
- m sl "$@"
-}
-# plain limited ssh
-ssh() {
- BRC=t command ssh "$@"
-}
-
# mail related
testmail() {