Skip to content

Commit aed64c6

Browse files
committed
+ add cp-into-docker-run oldratlee#83
1 parent f5d3862 commit aed64c6

File tree

2 files changed

+261
-43
lines changed

2 files changed

+261
-43
lines changed

bin/cp-into-docker-run

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
#!/bin/bash
2+
set -eEuo pipefail
3+
4+
PROG="$(basename "$0")"
5+
readonly PROG_VERSION='2.4.0-dev'
6+
7+
READLINK_CMD=readlink
8+
if command -v greadlink >/dev/null; then
9+
READLINK_CMD=greadlink
10+
fi
11+
12+
################################################################################
13+
# util functions
14+
################################################################################
15+
16+
# NOTE: $'foo' is the escape sequence syntax of bash
17+
readonly ec=$'\033' # escape char
18+
readonly eend=$'\033[0m' # escape end
19+
readonly nl=$'\n' # new line
20+
21+
redEcho() {
22+
# -t check: is a terminal device?
23+
[ -t 1 ] && echo "${ec}[1;31m$*$eend" || echo "$*"
24+
}
25+
26+
die() {
27+
redEcho "Error: $*" 1>&2
28+
exit 1
29+
}
30+
31+
usage() {
32+
local -r exit_code="${1:-0}"
33+
(($# > 0)) && shift
34+
# shellcheck disable=SC2015
35+
[ "$exit_code" != 0 ] && local -r out=/dev/stderr || local -r out=/dev/stdout
36+
37+
(($# > 0)) && redEcho "$*$nl" >$out
38+
39+
cat >$out <<EOF
40+
Usage: ${PROG} [OPTION]... command [command-args]...
41+
42+
Copy the command into docker container
43+
and run the command in container.
44+
45+
Example:
46+
${PROG} -c container_foo command_copied_into_container command_arg1
47+
48+
docker options:
49+
-c, --container destination docker container
50+
-u, --docker-user docker username or UID to run command
51+
optional, docker default is (maybe) root user
52+
-w, --workdir working directory inside the container
53+
optional, docker default is (maybe) root dir
54+
-t, --tmpdir tmp dir in docker to copy command
55+
optional, default is /tmp
56+
57+
run options:
58+
-v, --verbose show operation step infos
59+
60+
miscellaneous:
61+
-h, --help display this help and exit
62+
-V, --version display version information and exit
63+
EOF
64+
65+
exit "$exit_code"
66+
}
67+
68+
progVersion() {
69+
echo "$PROG $PROG_VERSION"
70+
exit
71+
}
72+
73+
################################################################################
74+
# parse options
75+
################################################################################
76+
77+
container_name=
78+
docker_user=
79+
docker_workdir=
80+
docker_tmpdir=/tmp
81+
verbose=false
82+
declare -a args=()
83+
84+
while (($# > 0)); do
85+
case "$1" in
86+
-c | --container)
87+
container_name="$2"
88+
shift 2
89+
;;
90+
-u | --docker-user)
91+
docker_user="$2"
92+
shift 2
93+
;;
94+
-w | --workdir)
95+
docker_workdir="$2"
96+
shift 2
97+
;;
98+
-t | --tmpdir)
99+
docker_tmpdir="$2"
100+
shift 2
101+
;;
102+
-v | --verbose)
103+
verbose=true
104+
shift
105+
;;
106+
-h | --help)
107+
usage
108+
;;
109+
-V | --version)
110+
progVersion
111+
;;
112+
--)
113+
shift
114+
args=(${args[@]:+"${args[@]}"} "$@")
115+
break
116+
;;
117+
-*)
118+
usage 2 "${PROG}: unrecognized option '$1'"
119+
;;
120+
*)
121+
# if not option, treat all follow args as command
122+
args=(${args[@]:+"${args[@]}"} "$@")
123+
break
124+
;;
125+
esac
126+
done
127+
128+
################################################################################
129+
# biz logic
130+
################################################################################
131+
132+
########################################
133+
# check docker command existence
134+
########################################
135+
136+
command -v docker &>/dev/null || die 'docker command not found!'
137+
138+
########################################
139+
# prepare vars for docker operation
140+
########################################
141+
142+
readonly specified_run_command="${args[0]}"
143+
run_command="$specified_run_command"
144+
if [ ! -f "$specified_run_command" ]; then
145+
which "$specified_run_command" &>/dev/null ||
146+
die "specified command not exists and not found in PATH: $specified_run_command"
147+
148+
run_command="$(which "$specified_run_command")"
149+
fi
150+
run_command="$($READLINK_CMD -f "$run_command")"
151+
152+
run_timestamp="$(date "+%Y%m%d_%H%M%S")"
153+
readonly uuid="${PROG}_${run_timestamp}_${$}_${RANDOM}"
154+
155+
run_command_base_name="$(basename "$run_command")"
156+
readonly run_command_dir_in_docker="$docker_tmpdir/$uuid"
157+
readonly run_command_in_docker="$run_command_dir_in_docker/$run_command_base_name"
158+
159+
cleanupWhenExit() {
160+
# remove tmp dir in docker by root user
161+
docker exec "${container_name}" rm -rf -- "$run_command_dir_in_docker" &>/dev/null
162+
}
163+
trap "cleanupWhenExit" EXIT
164+
165+
########################################
166+
# docker operations
167+
########################################
168+
169+
logAndRun() {
170+
$verbose && echo "[$PROG] $*" 1>&2
171+
"$@"
172+
}
173+
174+
logAndRun docker exec ${docker_user:+"--user=$docker_user"} "$container_name" \
175+
mkdir -p -- "$run_command_dir_in_docker"
176+
logAndRun docker cp "$run_command" "$container_name:$run_command_in_docker"
177+
logAndRun docker exec ${docker_user:+"--user=$docker_user"} "$container_name" \
178+
chmod +x "$run_command_in_docker"
179+
180+
logAndRun docker exec -i -t \
181+
${docker_user:+"--user=$docker_user"} \
182+
${docker_workdir:+"--workdir=$docker_workdir"} \
183+
"$container_name" \
184+
"$run_command_in_docker" "${args[@]:1:${#args[@]}}"

0 commit comments

Comments
 (0)