3 # Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
4 # based on vserver by Jacques Gelinas
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2, or (at your option)
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 # This is a script to control a virtual server
22 : ${UTIL_VSERVER_VARS:=/usr/lib/util-vserver/util-vserver-vars}
23 test -e "$UTIL_VSERVER_VARS" || {
24 echo $"Can not find util-vserver installation (the file '$UTIL_VSERVER_VARS' would be expected); aborting..." >&2
27 . "$UTIL_VSERVER_VARS"
30 USR_LIB_VSERVER=$__PKGLIBDIR
31 DEFAULTPATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/X11R6/bin
32 VINIT_CMD=/etc/rc.vinit
41 mkdir -p $1/proc $1/dev/pts
42 if [ ! -d $1/proc/1 ] ; then
43 mount -t proc none $1/proc
44 mount -t devpts -o gid=5,mode=0620 none $1/dev/pts
49 umount $1/proc 2>/dev/null
50 umount $1/dev/pts 2>/dev/null
53 # Check that the vservers parent directory has permission 000
54 # This is the key to avoid chroot escape
58 PERM=`$_SHOWPERM $__DEFAULT_VSERVERDIR/$1/..`
59 if [ "$PERM" != 000 ] ; then
61 echo "**********************************************************"
62 echo $__DEFAULT_VSERVERDIR/$1/.. has insecure permissions.
63 echo A vserver administrator may be able to visit the root server.
65 echo " " chmod 000 $__DEFAULT_VSERVERDIR/$1/..
66 echo do it anytime you want, even if vservers are running.
67 echo "**********************************************************"
72 # Extract the initial runlevel from the vserver inittab
75 INITDEFAULT=`grep :initdefault $__DEFAULT_VSERVERDIR/$1/etc/inittab | sed 's/:/ /g' | ( read a level b; echo $level)`
78 # Read the vserver configuration file, reusing the PROFILE value
79 # found in /var/run/vservers
82 if [ -f $__PKGSTATEDIR/$1.ctx ] ; then
83 . $__PKGSTATEDIR/$1.ctx
84 if [ "$S_PROFILE" != "" ] ; then
85 export PROFILE=$S_PROFILE
94 echo vserver [ options ] server-name command ...
96 echo server-name is a directory in $__DEFAULT_VSERVERDIR
98 echo The commands are:
99 echo " build : Create a virtual server by copying the packages"
100 echo " of the root server"
101 echo " enter : Enter in the virtual server context and starts a shell"
102 echo " Same as \"vserver name exec /bin/sh\""
103 echo " exec : Exec a command in the virtual server context"
104 echo " suexec : Exec a command in the virtual server context uid"
105 echo " service : Control a service inside a vserver"
106 echo " vserver name service service-name start/stop/restart/status"
107 echo " start : Starts the various services in the vserver, runlevel 3"
108 echo " stop : Ends all services and kills the remaining processes"
109 echo " running : Tells if a virtual server is running"
110 echo " It returns proper exit code, so you can use it as a test"
111 echo " status : Tells some information about a vserver"
112 echo " chkconfig : It turns a server on or off in a vserver"
114 echo "--silent : No informative messages about vserver context and IP numbers"
115 echo " Useful when you want to redirect the output"
127 CAPS="$CAPS --cap $f"
136 if [ "$1" = "--silent" ] ; then
143 # Setup the default ulimit for a vserver
145 # File handle are limited to half of the current system limit
146 # Virtual memory is limited to the ram size
147 NFILE=`cat /proc/sys/fs/file-max`
148 NFILE=`expr $NFILE / 2`
149 VMEM=`cat /proc/meminfo | grep MemTotal | (read a b c; echo $b)`
150 # Disabled for now, we need a different to set the security
151 # context limit than fiddling with ulimit
152 #ulimit -H -n $NFILE -v $VMEM
154 if [ $# -lt 2 ] ; then
156 elif [ "$2" = "build" ] ; then
157 # Either the directory does not exist or is empty
158 NBSUB=`ls $__DEFAULT_VSERVERDIR/$1 2>/dev/null | grep -v lost+found | wc -l`
160 if [ "$NBSUB" != 0 ] ; then
161 echo Virtual server $__DEFAULT_VSERVERDIR/$1 already exist
163 if [ ! -d $__DEFAULT_VSERVERDIR ] ; then
164 mkdir $__DEFAULT_VSERVERDIR || exit 1
165 chmod 000 $__DEFAULT_VSERVERDIR
166 echo Directory $__DEFAULT_VSERVERDIR was created with permissions 000
168 mkdir -p $__DEFAULT_VSERVERDIR/$1 || exit 1
169 chmod 755 $__DEFAULT_VSERVERDIR/$1
170 if test "$UTIL_VSERVER_AVOID_COPY"; then
171 mkdir -p $__DEFAULT_VSERVERDIR/$1/{etc/rc.d/init.d,sbin,var/run,var/log}
173 cp -ax /sbin /bin /etc /usr /var /lib $__DEFAULT_VSERVERDIR/$1/. || exit 1
175 cd $__DEFAULT_VSERVERDIR/$1 || exit 1
177 rm -f var/spool/mail/*
178 rm -f `find var/run -type f`
179 rm -f `find var/log -type f`
181 rm -f var/lock/subsys/*
182 rm -f etc/cron.d/kmod
183 mkdir proc tmp home root boot
184 test -f /root/.bashrc && cp -a /root/.bashrc root/.
185 test -f /root/.bash_profile && cp -a /root/.bash_profile root/.
188 # Create a minimal dev so the virtual server can't grab
191 vserver_mknod dev/null c 1 3 666
192 vserver_mknod dev/zero c 1 5 666
193 vserver_mknod dev/full c 1 7 666
194 vserver_mknod dev/random c 1 8 644
195 vserver_mknod dev/urandom c 1 9 644
196 vserver_mknod dev/tty c 5 0 666
197 vserver_mknod dev/ptmx c 5 2 666
199 # Turn off some service useless on a vserver
200 # vserver_turnoff apmd network autofs dhcpd gpm ipchains iptables \
201 # irda isdn keytable kudzu linuxconf-setup netfs nfs nfslock \
202 # pcmcia portmap pppoe random rawdevices rhnsd rstatd ruserd \
203 # rwalld rwhod sendmail smb snmpd v_httpd h_xinetd v_sshd vservers \
206 cd etc/init.d 2>/dev/null || cd etc/rc.d/init.d
210 *.bak|*~|functions|killall|halt|single)
213 #$USR_LIB_VSERVER/capchroot $__DEFAULT_VSERVERDIR/$1 /sbin/chkconfig --level 2345 $serv off
214 $0 --silent $1 chkconfig --level 2345 $serv off
219 rm -f etc/rc.d/rc6.d/S*reboot
220 # Create a dummy /etc/fstab and /etc/mtab to please
221 # df and linuxconf. We use hdv1, which does not exist
222 # to remind the admin that it is not the real drive
223 echo /dev/hdv1 / ext2 defaults 1 1 >etc/fstab
224 echo /dev/hdv1 / ext2 rw 0 0 >etc/mtab
225 # Install the vreboot utility
226 cp -a "$_VREBOOT" sbin/.
227 ln -sf vreboot sbin/vhalt
229 echo Directory $__DEFAULT_VSERVERDIR/$1 has been populated
230 if [ ! -d $__CONFDIR ] ; then
233 echo Directory $__CONFDIR has been created
235 if [ ! -f $__CONFDIR/$1.conf ] ; then
236 CONF=$__CONFDIR/$1.conf
238 if [ "$PROFILE" = "" ] ; then
241 # Select the IP number assigned to the virtual server
242 # This IP must be one IP of the server, either an interface
244 # A vserver may have more than one IP. Separate them with spaces.
245 # do not forget double quotes.
247 # IPROOT="1.2.3.4 2.3.4.5"
248 # IPROOT="eth0:1.2.3.4 eth1:2.3.4.5"
249 # If the device is not specified, IPROOTDEV is used
253 # The netmask and broadcast are computed by default from IPROOTDEV
256 # You can define on which device the IP alias will be done
257 # The IP alias will be set when the server is started and unset
258 # when the server is stopped
260 # You can set a different host name for the vserver
261 # If empty, the host name of the main server is used
272 # Uncomment the onboot line if you want to enable this
273 # virtual server at boot time
275 # You can set a different NIS domain for the vserver
276 # If empty, the current on is kept
277 # Set it to "none" to have no NIS domain set
279 # You can set the priority level (nice) of all process in the vserver
280 # Even root won't be able to raise it
282 # You can set various flags for the new security context
283 # lock: Prevent the vserver from setting new security context
284 # sched: Merge scheduler priority of all processes in the vserver
285 # so that it acts a like a single one.
286 # nproc: Limit the number of processes in the vserver according to ulimit
287 # (instead of a per user limit, this becomes a per vserver limit)
288 # private: No other process can join this security context. Even root
289 # Do not forget the quotes around the flags
291 # You can set various ulimit flags and they will be inherited by the
292 # vserver. You enter here various command line argument of ulimit
293 # ULIMIT="-HS -u 200"
294 # The example above, combined with the nproc S_FLAGS will limit the
295 # vserver to a maximum of 200 processes
296 #ULIMIT="-HS -u 1000"
298 # You can set various capabilities. By default, the vserver are run
299 # with a limited set, so you can let root run in a vserver and not
300 # worry about it. He can't take over the machine. In some cases
301 # you can to give a little more capabilities (such as CAP_NET_RAW)
302 # S_CAPS="CAP_NET_RAW"
304 # Select an unused context (this is optional)
305 # The default is to allocate a free context on the fly
306 # In general you don't need to force a context
309 echo $CONF has been created. Look at it\!
312 elif [ ! -f $__CONFDIR/$1.conf ] ; then
313 echo No configuration for this vserver: $__CONFDIR/$1.conf
315 elif [ ! -d $__DEFAULT_VSERVERDIR/$1/. ] ; then
316 echo No directory for this vserver: $__DEFAULT_VSERVERDIR/$1
318 elif [ "$2" = "start" ] ; then
319 echo Starting the virtual server $1
323 test -x $__CONFDIR/$1.sh && $__CONFDIR/$1.sh pre-start $1
328 cd $__DEFAULT_VSERVERDIR/$1 || exit 1
330 if [ "$PROFILE" != "" ] ; then
331 echo export PROFILE=$PROFILE >etc/PROFILE
334 rm -f `find var/run -type f`
336 chgrp ${UTMP_GROUP:-utmp} var/run/utmp
337 chmod 0664 var/run/utmp
338 rm -f var/lock/subsys/*
339 mountproc $__DEFAULT_VSERVERDIR/$1
347 STARTCMD="/etc/rc.d/rc $INITDEFAULT"
348 if [ -x $__DEFAULT_VSERVERDIR/$1/etc/init.d/rc ] ; then
349 STARTCMD="/etc/init.d/rc $INITDEFAULT"
350 elif [ -x $__DEFAULT_VSERVERDIR/$1/usr/bin/emerge ] ; then
351 STARTCMD="/sbin/rc default"
352 elif [ -x $__DEFAULT_VSERVERDIR/$1/etc/rc.d/rc.M ] ; then
353 STARTCMD="/etc/rc.d/rc.M"
358 for f in $S_FLAGS dummy
366 FLAGS="$FLAGS --flag fakeinit"
367 STARTCMD=/sbin/minit-start
368 DISCONNECT=--disconnect
373 FLAGS="$FLAGS --flag $f"
375 DISCONNECT=--disconnect
378 FLAGS="$FLAGS --flag $f"
382 if [ "$FAKEINIT" = "" ] ; then
383 $USR_LIB_VSERVER/fakerunlevel $INITDEFAULT var/run/utmp
386 calculateCaps $S_CAPS
388 if [ "$S_CONTEXT" != "" ] ; then
389 CTXOPT="--ctx $S_CONTEXT"
391 if [ "$S_HOSTNAME" != "" ] ; then
392 HOSTOPT="--hostname $S_HOSTNAME"
393 export HOSTNAME=$S_HOSTNAME
395 if [ "$S_DOMAINNAME" != "" ] ; then
396 DOMAINOPT="--domainname $S_DOMAINNAME"
398 if [ "$S_NICE" != "" ] ; then
399 NICECMD="nice -$S_NICE"
401 mkdir -p $__PKGSTATEDIR
402 chmod 700 $__PKGSTATEDIR
404 if [ "$ULIMIT" != "" ] ; then
409 # We switch to /vservers/$1 now, because after the
410 # security context switch /vservers directory becomes a dead zone.
411 cd $__DEFAULT_VSERVERDIR/$1
412 export PATH=$DEFAULTPATH
413 # XXX execute /etc/rc.vinit first for backward compatibility
414 for CMD in "$VINIT_CMD $2" "$STARTCMD" ; do
416 $_CHCONTEXT_COMPAT $SILENT $DISCONNECT $CAPS $FLAGS $CTXOPT $HOSTOPT $DOMAINOPT --secure \
417 $_SAVE_S_CONTEXT $__PKGSTATEDIR/$1.ctx \
418 $_CAPCHROOT $CHROOTOPT . $CMD
421 test ! -x $__CONFDIR/$1.sh || $__CONFDIR/$1.sh post-start $1
423 elif [ "$2" = "running" ] ; then
424 if [ ! -f $__PKGSTATEDIR/$1.ctx ] ; then
425 echo Server $1 is not running
428 . $__PKGSTATEDIR/$1.ctx
429 NB=$($USR_SBIN/vps ax | awk '{print $2}' | grep \^$S_CONTEXT\$ | wc -l)
430 #NB=`$_CHCONTEXT_COMPAT --silent --ctx $S_CONTEXT ps ax | wc -l`
431 #NB=`eval expr $NB + 0`
432 if [ "$NB" -gt 0 ] ; then
433 echo Server $1 is running
436 echo Server $1 is not running
440 elif [ "$2" = "status" ] ; then
443 . $__PKGSTATEDIR/$1.ctx
444 NB=$($USR_SBIN/vps ax | awk '{print $2}' | grep \^$S_CONTEXT\$ | wc -l)
445 echo $NB processes running
446 echo Vserver uptime: `$USR_LIB_VSERVER/filetime $__PKGSTATEDIR/$1.ctx`
448 elif [ "$2" = "stop" ] ; then
449 echo Stopping the virtual server $1
455 test -x $__CONFDIR/$1.sh && $__CONFDIR/$1.sh pre-stop $1
456 cd $__DEFAULT_VSERVERDIR/$1
457 mountproc $__DEFAULT_VSERVERDIR/$1
458 # The fakeinit flag tell us how to turn off the server
460 export PREVLEVEL=$INITDEFAULT
461 STOPCMD="/etc/rc.d/rc 6"
462 if [ -x $__DEFAULT_VSERVERDIR/$1/etc/init.d/rc ] ; then
463 STOPCMD="/etc/init.d/rc 6"
464 elif [ -x $__DEFAULT_VSERVERDIR/$1/usr/bin/emerge ] ; then
465 STOPCMD="/sbin/rc shutdown"
466 elif [ -x $__DEFAULT_VSERVERDIR/$1/etc/rc.d/rc.6 ] ; then
467 STOPCMD="/etc/rc.d/rc.6"
470 for f in $S_FLAGS dummy
475 FLAGS="$FLAGS --flag fakeinit"
476 STOPCMD="/sbin/minit-stop"
480 FLAGS="$FLAGS --flag $f"
481 STOPCMD="/sbin/init 6"
488 calculateCaps $S_CAPS
490 cd $__DEFAULT_VSERVERDIR/$1
491 export PATH=$DEFAULTPATH
492 # XXX execute /etc/rc.vinit first for backward compatibility
493 for CMD in "$VINIT_CMD $2" "$STOPCMD" ; do
494 $_CHCONTEXT_COMPAT $SILENT $CAPS --secure --ctx $S_CONTEXT \
495 $_CAPCHROOT . $STOPCMD
498 if test "$IS_MINIT"; then
499 echo "Waiting for minit finish-signal"
500 dd if=var/run/minit-stop of=/dev/zero bs=1 count=1 &>/dev/null
503 echo sleeping 5 seconds
507 echo Killing all processes
508 $_CHCONTEXT_COMPAT $CAPS --secure --silent --ctx $S_CONTEXT \
511 # We umount anyway, because "enter" establish the mount
512 # but when you exit, the server is considered not running
513 umountproc $__DEFAULT_VSERVERDIR/$1
515 test -x $__CONFDIR/$1.sh && $__CONFDIR/$1.sh post-stop $1
516 elif [ "$2" = "restart" ] ; then
522 elif [ "$2" = "suexec" ] ; then
523 if [ -z "$3" ] ; then
524 echo "Missing user!" >&2
525 echo "vserver vserver-name suexec user command [ args ... ]" >&2
527 elif [ -z "$4" ] ; then
528 echo "Missing command and arguments!" >&2
529 echo "vserver vserver-name suexec user command [ args ... ]" >&2
534 cd $__DEFAULT_VSERVERDIR/$1
535 mountproc $__DEFAULT_VSERVERDIR/$1
536 PS1="[\u@vserver:$1 \W]"
542 for f in $S_CAPS dummy
551 CAPS="$CAPS --cap $f"
556 for f in $S_FLAGS dummy
560 FLAGS="$FLAGS --flag fakeinit"
566 FLAGS="$FLAGS --flag $f"
571 if [ "$ULIMIT" != "" ] ; then
574 if $0 $VSERVER running >/dev/null
576 . $__PKGSTATEDIR/$VSERVER.ctx
577 cd $__DEFAULT_VSERVERDIR/$VSERVER
578 export PATH=$DEFAULTPATH
579 exec $_CHCONTEXT_COMPAT $SILENT $FLAGS $CAPS --secure --ctx $S_CONTEXT \
580 $_CAPCHROOT --suid $USERID . "$@"
582 test -x $__CONFDIR/$1.sh && $__CONFDIR/$1.sh pre-start $1
586 if [ "$S_CONTEXT" != "" ] ; then
587 CTXOPT="--ctx $S_CONTEXT"
589 if [ "$S_HOSTNAME" != "" ] ; then
590 HOSTOPT="--hostname $S_HOSTNAME"
591 export HOSTNAME=$S_HOSTNAME
593 if [ "$S_DOMAINNAME" != "" ] ; then
594 DOMAINOPT="--domainname $S_DOMAINNAME"
596 mkdir -p $__PKGSTATEDIR
597 cd $__DEFAULT_VSERVERDIR/$VSERVER
598 export PATH=$DEFAULTPATH
599 exec $_CHCONTEXT_COMPAT $SILENT $FLAGS $CAPS --secure $CTXOPT $HOSTOPT $DOMAINOPT \
600 $_SAVE_S_CONTEXT $__PKGSTATEDIR/$VSERVER.ctx \
601 $_CAPCHROOT --suid $USERID $CHROOTOPT . "$@"
604 elif [ "$2" = "exec" ] ; then
607 exec $0 $SILENT $VSERV suexec root "$@"
608 elif [ "$2" = "enter" ] ; then
610 exec $0 $SILENT $1 exec /bin/bash -login
611 elif [ "$2" = "service" ] ; then
615 exec $0 $SILENT $VSERVER exec /sbin/service "$@"
616 elif [ "$2" = "chkconfig" ] ; then
620 if [ "$1" = "--level" ] ; then
625 if [ $# != 2 -a ! -x $__DEFAULT_VSERVERDIR/$VSERVER/sbin/chkconfig ] ; then
626 echo Invalid argument, expected vserver name chkconfig [ --level nnn ] service on\|off
627 elif [ -x $__DEFAULT_VSERVERDIR/$VSERVER/sbin/chkconfig ] ; then
628 exec $0 --silent $VSERVER exec /sbin/chkconfig "$@"
629 elif [ -x $__DEFAULT_VSERVERDIR/$VSERVER/usr/sbin/update-rc.d ] ; then
630 if [ "$2" = "on" -o "$2" = "start" ] ; then
631 $0 --silent $VSERVER exec /usr/sbin/update-rc.d -f $1 remove >/dev/null
632 exec $0 --silent $VSERVER exec /usr/sbin/update-rc.d $1 start 80 2 3 4 5 . stop 20 0 1 6 . >/dev/null
633 elif [ "$2" = "off" -o "$2" = "stop" ] ; then
634 $0 --silent $VSERVER exec /usr/sbin/update-rc.d -f $1 remove >/dev/null
635 exec $0 --silent $VSERVER exec /usr/sbin/update-rc.d $1 stop 20 0 1 2 3 4 5 6 . >/dev/null
637 echo vserver chkconfig: Expecting on or off
640 echo chkconfig functionality is not available on this
641 echo vserver distribution.
642 echo Looked for /sbin/chkconfig and /usr/sbin/update-rc.d
645 echo Command unknown $2