aboutsummaryrefslogtreecommitdiffstats
path: root/pars.sh
blob: 58396903bd85759ab14bab6d9ff1af0af014a3b8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#!/bin/bash

parssh () {
    (( $# )) || {
        _parssh_usage
        return $?
    }
    local origopts=$-
    set -m
    local _parssh_prepend_host=true
    while [[ "$1" == -* ]]; do
        case ${1#-} in
            [0-9]*)
                [[ "${1#-}" != *[^0-9]* ]] && {
                    local _parssh_concurrency=${1#-}
                }
            ;;
            s|-servers)
                [[ -r "$2" ]] || {
                    echo "'$2': invalid file name or permissions issue"
                    return 99
                }
                local _parssh_servers="$2"
                shift
            ;;
            r|-rinput)
                [[ -r "$2" ]] || {
                    echo "'$2': invalid file name or permissions issue"
                    return 98
                }
                local _parssh_rinput="$2"
                shift
            ;;
            b|-bare)
                unset _parssh_prepend_host
            ;;
            h|-help)
                _parssh_usage
                return $?
            ;;
        esac
        shift
    done

    [[ -z "$_parssh_servers" ]] && {
        exec 9<&0
    } || {
        exec 9<"$_parssh_servers"
    }

    while read host; do
        while (( $(jobs -pr | wc -l) >= ${_parssh_concurrency:-4} )); do
            sleep 1
        done
        if [[ -z "$_parssh_rinput" ]]; then
            ssh -no StrictHostKeyChecking=no $host "$@" |\
                _parssh_host_prepend &
        else
            ssh -To StrictHostKeyChecking=no $host "$@" < "$_parssh_rinput" |\
                _parssh_host_prepend &
        fi
    done <&9
    wait
    exec 9>&-
    [[ "${origopts//[^m]/}" == "m" ]] || set +m
}

_parssh_host_prepend ()
    while read -r; do
        printf "${_parssh_prepend_host+$host: }%s\n" "$REPLY"
    done

_parssh_usage () {
    printf '  %s\n'\
        "SYNOPSIS"\
        "parssh [-NUM] [-r|--rinput FILE] [-s|--servers FILE] [-b|--bare] [COMMANDS] [< SERVERS]"\
        ""\
        "DESCRIPTION"\
        "  -NUM  (default: 4)"\
        "     Number of concurrent ssh connections to maintain.  E.g. '-40'."\
        "  -r FILE, --rinput FILE  (default: unset/inactive)"\
        "     File to send as STDIN redirection on remote servers."\
        "     (Can be used as replacement for or in conjunction with COMMANDS)."\
        "  -s FILE, --servers FILE  (default: unset/inactive)"\
        "     File to use as list of servers to run COMMANDS on."\
        "     (Cannot be used in conjunction with a server list on STDIN)."\
        "  -b, --bare  (default: unset/inactive)"\
        "     Disable prepending of hostname to each output line returned by COMMANDS on SERVERS."\
        "  COMMANDS"\
        "     The list of commands to be executed remotely by SSH on each SERVER."\
        "  < SERVERS"\
        "     Unless '-s' flag is used, STDIN will be used as list of remote servers."\
        "     (Deliniated by whitespace)."
    return 1
}