diff options
author | Tom Ryder <tom@sanctum.geek.nz> | 2022-08-04 13:57:28 +1200 |
---|---|---|
committer | Tom Ryder <tom@sanctum.geek.nz> | 2022-08-04 13:57:28 +1200 |
commit | 092ec85c19f3c7809df522f58004a87dbec476d3 (patch) | |
tree | 8a84d613e7340523225f1359aca7d78bbc7b2a39 | |
parent | Use long GDB option (diff) | |
download | dotfiles-092ec85c19f3c7809df522f58004a87dbec476d3.tar.gz dotfiles-092ec85c19f3c7809df522f58004a87dbec476d3.zip |
Support SSH many-Host lines and config subfiles
-rw-r--r-- | README.md | 2 | ||||
-rw-r--r-- | bash/bash_completion.d/_ssh_config_hosts.bash | 29 | ||||
-rw-r--r-- | bin/sls.sh | 3 | ||||
-rw-r--r-- | bin/slsf.awk | 29 | ||||
-rw-r--r-- | man/man1/sls.1df | 8 | ||||
-rw-r--r-- | man/man1/slsf.1df | 8 | ||||
-rw-r--r-- | man/man7/dotfiles.7df | 4 | ||||
-rw-r--r-- | vim/filetype.vim | 15 |
8 files changed, 64 insertions, 34 deletions
@@ -417,7 +417,7 @@ interactive shells. These scripts are installed by the `install-bin` target: - Three SSH-related scripts: - - `sls(1df)` prints hostnames read from a `ssh_config(5)` file. It uses + - `sls(1df)` prints hostnames read from `ssh_config(5)` files. It uses `slsf(1df)` to read each one. - `sra(1df)` runs a command on multiple hosts read from `sls(1df)` and prints output. diff --git a/bash/bash_completion.d/_ssh_config_hosts.bash b/bash/bash_completion.d/_ssh_config_hosts.bash index 0959f52b..16265e8a 100644 --- a/bash/bash_completion.d/_ssh_config_hosts.bash +++ b/bash/bash_completion.d/_ssh_config_hosts.bash @@ -3,23 +3,28 @@ _ssh_config_hosts() { # Iterate through SSH client config paths local config - for config in "$HOME"/.ssh/config /etc/ssh/ssh_config ; do + for config in /etc/ssh/ssh_config.d/*.conf /etc/ssh/ssh_config \ + "$HOME"/.ssh/config.d/*.conf "$HOME"/.ssh/config ; do [[ -e $config ]] || continue - # Read 'Host' options and their first value from file - local option value ci - while read -r option value _ ; do + # Read 'Host' options and their patterns from file + local option value patterns pattern ci + while read -r option value ; do [[ $option == Host ]] || continue + read -a patterns -r \ + < <(printf '%s\n' "$value") # Check host value - case $value in - # No empties - '') ;; - # No wildcards - *'*'*) ;; - # Found a match; print it - "$2"*) COMPREPLY[ci++]=$value ;; - esac + for pattern in "${patterns[@]}" ; do + case $pattern in + # No empties + '') ;; + # No wildcards + *'*'*) ;; + # Found a match; print it + "$2"*) COMPREPLY[ci++]=$pattern ;; + esac + done done < "$config" done @@ -3,7 +3,8 @@ # If we weren't given a file explicitly, we'll try to read both /etc/ssh_config # and ~/.ssh_config in that order if they exist if [ "$#" -eq 0 ] ; then - for cfg in /etc/ssh_config "$HOME"/.ssh/config ; do + for cfg in /etc/ssh_config.d/*.conf /etc/ssh_config \ + "$HOME"/.ssh/config.d/*.conf "$HOME"/.ssh/config ; do [ -e "$cfg" ] || continue set -- "$@" "$cfg" done diff --git a/bin/slsf.awk b/bin/slsf.awk index 3d5c190f..87127a2c 100644 --- a/bin/slsf.awk +++ b/bin/slsf.awk @@ -1,9 +1,28 @@ -# Print the first non-glob "Host" name from each line of ssh_config(5) files +# Print all the hosts from ssh_config(1) files # Manage the processing flag (starts set in each file) -FNR == 1 || /### sls/ { sls = 1 } +BEGIN { sls = 1 } +FNR { sls = 1 } +/### sls/ { sls = 1 } /### nosls/ { sls = 0 } -# If processing flag set, directive is "Host", and hostname has no wildcards, -# then print it -sls && $1 == "Host" && $2 !~ /\*/ { print $2 } +# Skip if we're ignoring hosts +!sls { next } +# Skip if this isn't a host line +$1 != "Host" { next } + +# Add all the patterns after the keyword that don't have wildcards +{ + for (i = 2; i <= NF; i++) { + if ($i !~ /[?*]/) { + hosts[$i]++ + } + } +} + +# Print the complete list of hosts, sorted +END { + for (host in hosts) { + print host | "sort" + } +} diff --git a/man/man1/sls.1df b/man/man1/sls.1df index 83c13201..dde8e622 100644 --- a/man/man1/sls.1df +++ b/man/man1/sls.1df @@ -1,4 +1,4 @@ -.TH SLS 1df "May 2014" "Manual page for sls" +.TH SLS 1df "August 2022" "Manual page for sls" .SH NAME .B sls \- list the first hostname on each line of an ssh_config(5) file @@ -10,9 +10,9 @@ ssh_config_alt1 ssh_config_alt2 .SH DESCRIPTION .B sls runs slsf(1df) on the given set of ssh_config(5) files to print the first -non-wildcard hostname on each "Host" line, defaulting to /etc/ssh/ssh_config -and ~/.ssh/config if they exist. Suitable for use in batch scripts like -sra(1df). +non-wildcard hostname on each "Host" line, defaulting to +/etc/ssh/ssh_config.d/*.conf, /etc/ssh/ssh_config, ~/.ssh/config.d/*.conf, and +~/.ssh/config if they exist. Suitable for use in batch scripts like sra(1df). .SH SEE ALSO slsf(1df), sra(1df), sta(1df), ssh(1), ssh_config(5) .SH AUTHOR diff --git a/man/man1/slsf.1df b/man/man1/slsf.1df index 31453dca..6d59ba3d 100644 --- a/man/man1/slsf.1df +++ b/man/man1/slsf.1df @@ -1,4 +1,4 @@ -.TH SLSF 1df "July 2016" "Manual page for slsf" +.TH SLSF 1df "August 2022" "Manual page for slsf" .SH NAME .B slsf \- list the first hostname on each line of ssh_config(5) files @@ -10,9 +10,9 @@ cat ~/.ssh_config | .br .SH DESCRIPTION .B slsf -iterates through the ssh_config(5) files given as its input and prints the -first name given on each "Host" line, as long as it contains no wildcards. -Most users will probably want the sls(1df) frontend. +iterates through the ssh_config(5) files given as its input and prints a unique +list of the patterns given on each "Host" line containing no wildcards. Most +users will probably want the sls(1df) frontend instead. .P Within the file, a comment "### nosls" on its own line will exclude all following output unless an "### sls" comment is read to resume it again: diff --git a/man/man7/dotfiles.7df b/man/man7/dotfiles.7df index 8c766c05..cae361a2 100644 --- a/man/man7/dotfiles.7df +++ b/man/man7/dotfiles.7df @@ -573,8 +573,8 @@ These scripts are installed by the \f[C]install-bin\f[R] target: Three SSH-related scripts: .RS 2 .IP \[bu] 2 -\f[C]sls(1df)\f[R] prints hostnames read from a \f[C]ssh_config(5)\f[R] -file. +\f[C]sls(1df)\f[R] prints hostnames read from \f[C]ssh_config(5)\f[R] +files. It uses \f[C]slsf(1df)\f[R] to read each one. .IP \[bu] 2 \f[C]sra(1df)\f[R] runs a command on multiple hosts read from diff --git a/vim/filetype.vim b/vim/filetype.vim index 01cc0f3a..c616babd 100644 --- a/vim/filetype.vim +++ b/vim/filetype.vim @@ -434,18 +434,23 @@ augroup filetypedetect \ ?*.sql \ setfiletype sql " OpenSSH configuration + "" client autocmd BufNewFile,BufRead - \ ssh_config,*/.ssh/config + \ ssh_config + \,*/ssh_config.d/*.conf + \,*/.ssh/config, + \,*/.ssh/config.d/*.conf \ setfiletype sshconfig + "" server + autocmd BufNewFile,BufRead + \ sshd_config + \,*/sshd_config.d/*.conf + \ setfiletype sshdconfig " sudoers(5) autocmd BufNewFile,BufRead \ sudoers \,sudoers.tmp \ setfiletype sudoers - " OpenSSH server configuration - autocmd BufNewFile,BufRead - \ sshd_config - \ setfiletype sshdconfig " Subversion commit autocmd BufNewFile,BufRead \ svn-commit*.tmp |