-
Notifications
You must be signed in to change notification settings - Fork 1
/
snr.sh
executable file
·185 lines (162 loc) · 4.86 KB
/
snr.sh
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
#!/bin/sh
# Simple wrapper to quickly run systemd-nspawn containers
# (If you want to use it for other containers, not systemd-nspawn, please make a pull request)
# Author: Mikhail Novosyolov <[email protected]>
# License: MIT
for i in "/etc/snr.conf" "${PWD}/snr.conf"
do
if [ -f "$i" ]; then . "$i"; fi
done
CMD_NSPAWN="systemd-nspawn"
CMD_READELF="readelf"
CMD_TEST="test"
DIR="${DIR:-/var/lib/machines}"
X11_SOCKET_DIR="${X11_SOCKET_DIR:-/tmp/.X11-unix}"
PULSE_SERVER_TARGET="${PULSE_SERVER_TARGET-/tmp/snr_PULSE_SERVER}"
# NW - network
NW="${NW:-1}"
echo_help(){
man -P ul snr 2>/dev/null || \
echo "See https://github.com/mikhailnov/snr for documentation"
}
env_setup(){
# In some cases like using sudo initially exported variables may be lost,
# so let's reexport them on each shell init
env_file_local="$(mktemp)"
cat > "$env_file_local" <<EOF
export DISPLAY="$DISPLAY"
export LC_ALL="$LANG"
export PULSE_SERVER="$PULSE_SERVER_TARGET"
# Fix Qt4 GUIs ("invalid Pixmap or Window parameter")
export QT_X11_NO_MITSHM=1
EOF
# By default it is 0600 and not readable by users with different UID from inside container
# in many cases, e.g. inside ALT Linux, it must be executable
chmod 0755 "$env_file_local"
bind_options="${bind_options} --bind=${env_file_local}:/etc/profile.d/90-snr-tmp.sh"
}
path_workaround(){
# Workaround cases when some utilities, e.g. ip, are not in PATH, but still can be used
# Example: https://bugzilla.rosalinux.ru/show_bug.cgi?id=9918
PATH0="$PATH"
for i in '/sbin' '/usr/sbin' '/usr/local/sbin'
do
if ! echo "$PATH0" | sed -e 's,:,\n,g' | grep -q "^${i}\$" \
&& [ -d "$i" ] \
&& [ -r "$i" ]; then
export PATH="${i}:${PATH}"
fi
done
}
virtual_network(){
# virbr0 is a virtual bridge from livbirt with DHCP,
# we can attach our containers to the same network as libvirt VMs and LXC containers.
BRIDGE="${BRIDGE:-$(ip a | grep ': virbr' | awk -F ': ' '{print $2}' | grep -v '\-' | sort -u | head -n 1)}"
if [ -n "$BRIDGE" ]; then
OTHER="${OTHER} --network-bridge=${BRIDGE}"
fi
}
verify_target(){
if ! $CMD_TEST -x "$1/bin/sh"; then
echo "$1 does not look like an OS tree, because $1/bin/sh was not found or is not executable"
return 1
fi
}
mk_target(){
if [ "$(echo "$1" | head -c 1)" = "/" ] && $CMD_TEST -d "/$1"; then
TARGET="/$1"
verify_target "$TARGET" && return
fi
if $CMD_TEST -d "${PWD}/$1"; then
TARGET="${PWD}/$1"
verify_target "$TARGET" && return
fi
if $CMD_TEST -d "${DIR}/$1"; then
TARGET="${DIR}/$1"
verify_target "$TARGET" && return
fi
echo "Neither ${PWD}/$1 nor ${DIR}/$1 have been found, cannot find directory with rootfs to run!"
exit 1
}
run_nspawn(){
if ! command -v ip 2>/dev/null >/dev/null; then path_workaround; fi
SUDO_CMD="$(command -v sudo)"
if [ "$(id -u)" != "0" ]
then if [ -x "${SUDO_CMD}" ]
then
# check ability to use sudo
if ! "${SUDO_CMD}" echo test > /dev/null 2>&1; then
echo "Unable to use sudo, run snr from root or setup sudoers"
exit 1
fi
CMD_NSPAWN="${SUDO_CMD} systemd-nspawn"
CMD_READELF="${SUDO_CMD} readelf"
CMD_TEST="${SUDO_CMD} test"
else echo "snr must be ran as root!" && exit 1
fi
fi
# http://ludiclinux.com/Nspawn-Steam-Container/
for i in \
"/dev/dri" \
"/dev/shm" \
"/dev/snd" \
"/dev/nvidia0" \
"/dev/nvidiactl" \
"/dev/nvidia-modeset"
do
if [ -r "$i" ]; then
bind_options="${bind_options} --bind=${i}"
fi
done
for i in "$X11_SOCKET_DIR"
do
if $CMD_TEST -r "$i"; then
bind_options="${bind_options} --bind-ro=${i}"
fi
done
PULSE_SERVER_LOCAL="$(LC_ALL=C pactl info | grep -i '^Server String:' | awk -F ':' '{print $NF}' | sed -e 's/^ *//' -e 's/ *$//')"
if [ -n "$PULSE_SERVER_LOCAL" ] && [ -e "$PULSE_SERVER_LOCAL" ]; then
bind_options="${bind_options} --bind=${PULSE_SERVER_LOCAL}:${PULSE_SERVER_TARGET}"
fi
env_setup
trap "rm -f $env_file_local" EXIT
mk_target "$TARGET"
echo "Using OS tree in ${TARGET}"
if [ "$NW" != 0 ]; then
if ! echo " $OTHER " | grep -qE ' -b | --boot ' && [ "$NW" != 2 ]
# If we are not booting the container, than network managing services won't start
# and won't setup network, so don't bind to a network bridge, otherwise network will not work;
# but NW=2 may be used to force always setting up the network.
then :
else virtual_network
fi
fi
# automatically set 32 bit CPU arch for containers with 32 bit OS
if $CMD_READELF -h "${TARGET}/bin/sh" | grep -q ' ELF32$'; then
OTHER="${OTHER} --personality=x86"
fi
( set -x
xhost +local:
$CMD_NSPAWN \
--setenv=DISPLAY="${DISPLAY}" \
--setenv=QT_X11_NO_MITSHM=1 \
--setenv=LC_ALL="${LANG}" \
${bind_options} \
-D "${TARGET}" \
${OTHER}
)
}
#--------------------------------------------------------------------------------
case "$1" in
-h | --help )
echo_help
exit
;;
* )
if [ -z "$1" ]; then echo_help; exit; fi
TARGET="$1"
shift
OTHER=" $* $other_options"
run_nspawn
;;
esac