summaryrefslogtreecommitdiff
path: root/update-all.in
blob: 8e8a211cd56e8030f5b30bdd4315170342e3f13b (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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#!/bin/bash

# update-all version #VERSION#
# updates all clients defined in #ETCDIR#/update-all.conf via local versions of update-me

. #ETCDIR#/update-all.conf

usage() {
  >&2 printf 'usage:\n'
  >&2 printf '  %s\n' "${0##*/}"
  >&2 printf '  %s -c\n' "${0##*/}"
  >&2 printf '  %s $id $tmpdir [cs]\n' "${0##*/}"
  exit 1
}

if [ "$#" -eq 3 ]; then
  system="${systems["$1"]}"
  if [ "${system}" == "localhost" ]
  then
    cmd=""
  else
    cmd="ssh -t -t ${system}"
  fi
  cmd="${cmd} update-me"
  case "$3" in
    'c')
      delay=1
      while sleep ${delay}; do
        ${cmd} -c </dev/null
        err=$?
        if [ "${err}" -ne 1 ]; then
          break
        fi
        if [ ${delay} -lt 10 ]; then
          delay=$((delay+1))
        fi
      done
    ;;
    's')
      ${cmd} -s
      err=$?
      if [ "${err}" -ne 0 ] \
      && [ -d "$2" ]; then
        printf '%s\n' "${err}" > "$2/$1"
      fi
    ;;
    *)
      usage
    ;;
  esac
  exit ${err}
fi

if [ "$#" -eq 1 ] \
&& [ "x$1" = 'x-c' ]; then
  for system in "${!systems[@]}"; do
    screen -S update-clear-all -d -m "${0}" "${system}" "${tmp_dir}" 'c'
  done
  exit
fi

if [ "$#" -ne 0 ]; then
  usage
fi

tmp_dir=$(mktemp -d)
trap 'rm -rf --one-file-system "${tmp_dir}"' EXIT

pids=()

for system in "${!systems[@]}"; do
  if [ -z "${DISPLAY}" ]; then
    screen -S update-all -d -m "${0}" "${system}" "${tmp_dir}" 's'
  else
    urxvt -title "${systems["${system}"]}: update-me" -e "${0}" "${system}" "${tmp_dir}" 's' &
    pids+=($!)
  fi
  screen -S update-clear-all -d -m "${0}" "${system}" "${tmp_dir}" 'c'
done

if [ -z "${DISPLAY}" ]; then
  sleep 1
  pids=(
    $(
      screen -list \
      | sed '
        s/^\s\+\([0-9]\+\)\.update-all\s.*$/\1/
        t
        d
      '
    )
  )
fi

while [ -n "${pids[*]}" ]; do
  if [ -z "${DISPLAY}" ]; then
    for pid in "${pids[@]}"; do
      if ! kill -0 "${pid}" >/dev/null 2>&1; then
        continue
      fi
      npids+=("${pid}")
      screen -r "${pid}"
    done
    pids=("${npids[@]}")
  else
    sleep 1
  fi
  pids=(
    $(
      for pid in "${pids[@]}"; do
        if kill -0 "${pid}" >/dev/null 2>&1; then
          printf '%s\n' "${pid}"
        fi
      done
    )
  )
done

ls "${tmp_dir}" \
| while read -r system; do
  err=$(
    cat "${tmp_dir}/${system}"
  )
  if [ "${err}" -ne 0 ]; then
    printf 'update-me on "%s" failed: %s\n' \
      "${systems["${system}"]}" \
      "${err}"
  fi
done

exit $(
  find "${tmp_dir}" -type f \
    -exec grep -lxFv '0' {} + \
  | wc -l
)