blob: 848c459c9e79efbcc55a9814365a1b791095dbf6 (
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
136
137
|
#!/bin/bash
# copy resumably with dd via network
script_name=$(basename "$0")
usage() {
>&2 printf 'usage:\n'
>&2 printf ' %s in-host in-dev out-dev log-file\n' "${script_name}"
>&2 printf ' %s -s in-dev start-position remote-port\n' "${script_name}"
exit 1
}
dd_options='bs=1M'
for needed in dd nc ss screen pgrep kill ssh; do
if ! which "${needed}" >/dev/null; then
>&2 printf 'please install required program %s\n' "${needed}"
exit 1
fi
done
if [ "x$1" = 'x-s' ]; then
shift
if [ $# -ne 3 ]; then
>&2 printf 'expected 3 arguments, got %s:\n' "$#"
>&2 printf '"%s" ' "$@"
>&2 printf '\n'
usage
fi
dev="$1"
start="$2"
remote_ip="${SSH_CLIENT%% *}"
if [ -z "${remote_ip}" ]; then
>&2 printf 'cannot obtain remote ip\n'
exit 1
fi
remote_port="$3"
if [ ! -r "${dev}" ]; then
>&2 printf 'cannot read from %s\n\n' "${dev}"
usage
fi
set +o pipefail
dd if="${dev}" ${dd_options} skip="${start}" 2>/dev/null | \
nc -cn "${remote_ip}" "${remote_port}"
exit $?
fi
if [ $# -ne 4 ]; then
usage
fi
remote_host="$1"
remote_dev="$2"
local_dev="$3"
log_file="$4"
if [ ! -w "${log_file%/*}" ] && [ ! -w "${log_file}" ]; then
>&2 printf 'cannot write/create log-file %s\n\n' "${log_file}"
usage
fi
if [ ! -w "${local_dev}" ]; then
>&2 printf 'cannot write to out-dev %s\n\n' "${local_dev}"
usage
fi
start=0
if [ -f "${log_file}" ]; then
start=$(
sed -n '
1 {
s/^start: //
p
q
}
' "${log_file}"
)
copied=$(
sed '
s/^\([0-9]\+\)+0 records out$/\1/
t
d
' "${log_file}" | \
sort -n | \
tail -n1
)
if [ -n "${copied}" ]; then
start=$((start+copied))
fi
fi
if pgrep -ax dd || pgrep -ax nc; then
>&2 printf 'another dd or nc is already running - this won'"'"'t work\n'
exit 1
fi
printf 'start: %s\n' "${start}" > \
"${log_file}"
screen -d -m bash -c '
set +o pipefail
nc -l -c | \
dd of="'"${local_dev}"'" '"${dd_options}"' seek='"${start}"' 2>>"'"${log_file}"'" >/dev/null
printf '"'"'\nwrite-pipe-exit: %s\n'"'"' $? >>"'"${log_file}"'"
'
for i in {1..20}; do
if [ -n "${port}" ]; then
break
elif [ ${i} -gt 1 ]; then
sleep 0.1
fi
nc_pid=$(
pgrep -x nc
)
dd_pid=$(
pgrep -x dd
)
port=$(
ss -nlp | \
grep -F ",pid=${nc_pid}," | \
awk '{print $5}' | \
sed 's/^.*://'
)
done
if [ -z "${port}" ]; then
>&2 printf 'could not determine listening port\n'
exit 1
fi
screen -d -m bash -c '
while kill -SIGUSR1 '"${dd_pid}"'; do
sleep 1
done
'
ssh "${remote_host}" "${script_name} -s ${remote_dev} ${start} ${port}"
printf '\nssh-exit: %s\n' $? >>"${log_file}"
|