-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathsing_command
executable file
·277 lines (226 loc) · 8.72 KB
/
sing_command
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
#!/bin/bash
# By Pierre Rioux, [email protected],
# November 2019, December 2019, January 2020
#
# See https://github.com/aces/sing-squashfs-support
#
# The site above gives examples on how to invoke this script as a wrapper for
#
# a) mounting squashfs files using sshfs;
# b) running rsync inside a container with squashfs files;
# c) running any other command too while we're at it.
#
# This program has many capabilities that are triggered
# automatically by how it is NAMED at installation. If it
# is called any of these names, some default behaviors will
# be triggered:
#
# sing_sftpd # passthrough container command: sftp-server
# sing_rsync # passthrough container command: rsync
# sing_command_here # default sqfs and image: in install dir
# sing_sftpd_here # default sqfs and image: in install dir
# sing_rsync_here # default sqfs and image: in install dir
VERSION="3.0"
BASENAME=$(basename $0)
PREFIX="" # -D option
# Important note for developers: the sshd <-> sftp-server
# connection (or the sshd <-> rsync connection) is performed strictly
# with STDIN and STDOUT, so we are not allowed to pollute any
# of these two streams while running this script! If you need to
# debug, echo stuff to files in /tmp instead. E.g. like in
#
# echo "inspecting prefix=$PREFIX" > /tmp/deb.1
#
# You can also add 'echo' in front of the final
# singularity command to inspect it, as a way
# to inspect its final form.
# Why oh why is this not at the same place?
# When the container is launched, we'll look for both.
RPM_OPEN_SSH_SFTPD="/usr/libexec/openssh/sftp-server" # Centos location
APT_OPEN_SSH_SFTPD="/usr/lib/sftp-server" # Ubuntu location
# Some build-in commands we support by default:
# For sing_sftpd : (automatically supports the two paths above too)
SFTPD_COMMAND="\$(type -p $RPM_OPEN_SSH_SFTPD || type -p $APT_OPEN_SSH_SFTPD)"
# For sing_rsync :
RSYNC_COMMAND="rsync" # hopefully it's in the search path in the container
# Documentation and usage statement
function usage() {
cat <<USAGE 1>&2
This is $BASENAME $VERSION by Pierre Rioux
It will run a command in a singularity container that has been started
with a set of overlays. By default, depending on the name of this
program, it will run the OpenSSH 'sftp-server', or the 'rsync' command.
Usage: $BASENAME [-D directory] [-I singularity_image_file] [-O overlay_file_pattern] [command...]
Note: options must be provided in the order shown!
where:
-D directory
is an optional base directory for finding both singulariy_image_file
and overlay_file_pattern. If provided, the program will chdir there
first before attempting to resolve the other arguments.
If a directory is given and no other arguments are provided
(that is, no singularity_image_file and no overlay_file_pattern),
then the program will pick the first file named "*.simg" (or
"*.sif") in the directory as its singularity image file, and
will pick all files ending in .squashfs, .sqs or .ext3 as the
overlays.
-I singularity_image_file
is a path to a singularity container image. The image must contain at
least the openssh-server package (when running sing_sftpd) or the rsync
package (when running sing_rsync). It can be a relative or absolute
path. See also -D above.
-O overlay_file_pattern
is a file pattern for a set of overlay image files
(e.g. /path/to/something*.squashfs).
command
an optional command to run in the container. By default the command
to run depends on the name of this very program:
When the program is named 'sing_sftpd':
The command will be $RPM_OPEN_SSH_SFTPD or $APT_OPEN_SSH_SFTPD
(whichever is first found). This is the OpenSSH sftp-server.
When the program is named 'sing_rsync':
The command will be '$RSYNC_COMMAND'.
Installation shortcut:
If this program is installed in a directory and renamed with
a '_here' at the end of the name, it will automatically internally
assume that a '-D' option was provided with the path to the directory
where the script is installed as argument. E.g.
/path/to/sing_sftpd_here
is the same as
/path/to/sing_sftpd -D /path/to
Examples:
# Overlays are given with a pattern:
sing_sftpd -I centos.simg -O '*.squashfs'
# Using a -D to specify where to look for all the files:
sing_rsync -D /my/path -I centos.simg -O '*.squashfs' rsync_args_here
# Using a -D to specify where to look just for the overlays:
sing_sftpd -D /my/path -I /some/other/place/centos.simg -O '*.squashfs'
# Using a -D and no other arguments:
# a) singularity image will be first .simg (or .sif)
# b) overlays will be all .squashfs, .sqs or .ext3 files
sing_sftpd -D /my/path/for/everything
USAGE
exit 2
}
##########################################
# When this program is renamed to end with
# the string "_here", then it behaves as
# if the option "-D $PWD" was given.
##########################################
if test "X${BASENAME/*_here/Y}" = "XY" ; then
# Note that 'readlink -e' only exists on Linux
PREFIX=$(dirname $(readlink -e "$0")) || exit
fi
####################################
# Validation of arguments
####################################
if test -z "$PREFIX" -a $# -lt 2 ; then
usage
fi
# Optional PREFIX in -D
if test "X$1" = "X-D" ; then
PREFIX="$2"
shift ; shift
if ! test -d "$PREFIX" ; then
echo "Error: '$PREFIX' for option -D is not a directory." 1>&2
exit 2
fi
fi
# Option -I: the path of the singularity image
if test "X$1" = "X-I" ; then
test $# -lt 2 && usage
SING_IMAGE="$2" # can be empty string if -D provided
shift ; shift
fi
# Option -O: the path (or pattern) for one or several overlay images
if test "X$1" = "X-O" ; then
test $# -lt 2 && usage
OVERLAYS="$2"; # can also be empty if -D provided
shift ; shift
fi
# Find image and overlays if necessary
if test -n "$PREFIX" ; then
# This is important, and it makes all the path
# resolution code below relative to it now.
cd "$PREFIX" || exit 2
# Auto find image
if test -z "$SING_IMAGE" ; then # if no image given, find one
SING_IMAGE=$(ls -1 | egrep '\.simg$|\.sif$' | head -1)
if test -z "$SING_IMAGE" ; then
echo "Error: can't find a .simg or .sif image in directory '$PREFIX'." 1>&2
exit 2
fi
fi
# Auto find overlays
if test -z "$OVERLAYS" ; then
OVERLAYS=$(ls -1 | egrep '\.squashfs$|\.sqs$|\.ext3$')
fi
fi
# Validate image file
if ! test -f "$SING_IMAGE" ; then
test -n "$PREFIX" && echo "Error: while switched to directory '$PREFIX':" 1>&2
echo "Error: '$SING_IMAGE' doesn't seem to be present and an image file." 1>&2
echo "Maybe you need to provide the path with -I ?" 1>&2
exit 2
fi
# Validate overlays patterns
if test -z "$OVERLAYS" ; then
echo "Error: no patterns for the overlays files provided." 1>&2
echo "Maybe you need to provide the path with -O ?" 1>&2
exit 2
fi
# Generate singularity overlays options, expanding patterns at the same time.
# Note that this is a place where errors can occur silently:
# if the user provide bad patterns that do not match any files, the
# pattern will be ignored.
SING_OVERLAYS=$(ls -1 $OVERLAYS | sed -e 's/^/--overlay=/' -e 's/\.sqs$/.sqs:ro/' -e 's/\.squashfs/.squashfs:ro/')
# Figure out what program to run now;
# if this script is provided with a command, we run that;
# if this script is named "sing_sftpd", we run the OpenSSH sftp-server;
# if this script is named "sing_rsync", we run the rsync command.
# if this script is named "sing_shell", we start an interactive shell with no command.
COMMAND=""
MODE="exec"
if echo $BASENAME | grep sing_sftpd >/dev/null ; then
COMMAND="$SFTPD_COMMAND"
elif echo $BASENAME | grep sing_rsync >/dev/null ; then
COMMAND="$RSYNC_COMMAND"
elif echo $BASENAME | grep sing_shell >/dev/null ; then
MODE="shell"
fi
# Help messages
if test "X$*" = "X-h" -o "X$*" = "X-help" -o "X$*" = "X--help" ; then
usage
exit 2
fi
# EXEC requires a command
if test "$MODE" = "exec" ; then
if test -z "$COMMAND" && test -z "$*" ; then
echo "Error: we do not know what command to run in the container." 1>&2
echo "Try \"$0 -h\" for help" 1>&2
exit 2
fi
fi
# SHELL requires no commands
if test "$MODE" = "shell" ; then
if test -n "$COMMAND" || test -n "$*" ; then
echo "Error: when starting an interactive shell, no commands are allowed." 1>&2
echo "Try \"$0 -h\" for help" 1>&2
exit 2
fi
fi
if test $MODE = "exec" ; then
# OK do the main work now.
#
# I use two 'exec's to simplify the process hierarchy!
#
# How glorious!
exec singularity -s exec \
$SING_OVERLAYS \
$SING_IMAGE \
bash -c "exec $COMMAND $*"
else # interactive shell
exec singularity -s shell \
$SING_OVERLAYS \
$SING_IMAGE
fi
# If bash reaches this point, something is clearly wrong.