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:=$(dirname $0)/util-vserver-vars}
23 test -e "$UTIL_VSERVER_VARS" || {
24 echo "Can not find util-vserver installation; aborting..."
27 . "$UTIL_VSERVER_VARS"
30 USR_LIB_VSERVER=$PKGLIBDIR
32 VSERVER_CMD=$USR_SBIN/vserver
33 WAITFOR_CMD="waitfor 60"
34 VINIT_CMD=/etc/rc.vinit
35 CHCONTEXT_CMD=$USR_SBIN/chcontext
36 SAVE_S_CONTEXT_CMD=$USR_LIB_VSERVER/save_s_context
37 CAPCHROOT_CMD=$USR_LIB_VSERVER/capchroot
38 VSERVERKILLALL_CMD=$USR_LIB_VSERVER/vserverkillall
39 DEFAULTPATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/X11R6/bin
48 mkdir -p $1/proc $1/dev/pts
49 if [ ! -d $1/proc/1 ] ; then
50 mount -t proc none $1/proc
51 mount -t devpts -o gid=5,mode=0620 none $1/dev/pts
56 umount $1/proc 2>/dev/null
57 umount $1/dev/pts 2>/dev/null
60 # Check that the vservers parent directory has permission 000
61 # This is the key to avoid chroot escape
65 PERM=`$USR_LIB_VSERVER/showperm $VROOTDIR/$1/..`
66 if [ "$PERM" != 000 ] ; then
68 echo "**********************************************************"
69 echo $VROOTDIR/$1/.. has insecure permissions.
70 echo A vserver administrator may be able to visit the root server.
72 echo " " chmod 000 $VROOTDIR/$1/..
73 echo do it anytime you want, even if vservers are running.
74 echo "**********************************************************"
79 # Extract the initial runlevel from the vserver inittab
82 INITDEFAULT=`grep :initdefault $VROOTDIR/$1/etc/inittab | sed 's/:/ /g' | ( read a level b; echo $level)`
85 # Read the vserver configuration file, reusing the PROFILE value
86 # found in /var/run/vservers
89 if [ -f /var/run/vservers/$1.ctx ] ; then
90 . /var/run/vservers/$1.ctx
91 if [ "$S_PROFILE" != "" ] ; then
92 export PROFILE=$S_PROFILE
96 . /etc/vservers/$1.conf
99 # Wait for a process to finish for $1 seconds.
104 # Background the process.
106 # Wait for it to finish.
107 while [ $timeout -gt 0 ] ; do
109 kill -0 $! 2>/dev/null || break
110 timeout=$(($timeout - 1))
112 # Try nicely terminating it, then just kill it.
113 if [ $timeout -eq 0 ] ; then
114 kill -TERM $! && kill -0 $! 2>/dev/null && kill -KILL $!
122 echo vserver [ options ] server-name command ...
124 echo server-name is a directory in $VROOTDIR
126 echo The commands are:
127 echo " build : Create a virtual server by copying the packages"
128 echo " of the root server"
129 echo " enter : Enter in the virtual server context and starts a shell"
130 echo " Same as \"vserver name exec /bin/sh\""
131 echo " exec : Exec a command in the virtual server context"
132 echo " suexec : Exec a command in the virtual server context uid"
133 echo " service : Control a service inside a vserver"
134 echo " vserver name service service-name start/stop/restart/status"
135 echo " start : Starts the various services in the vserver, runlevel 3"
136 echo " stop : Ends all services and kills the remaining processes"
137 echo " running : Tells if a virtual server is running"
138 echo " It returns proper exit code, so you can use it as a test"
139 echo " status : Tells some information about a vserver"
140 echo " chkconfig : It turns a server on or off in a vserver"
142 echo "--silent : No informative messages about vserver context and IP numbers"
143 echo " Useful when you want to redirect the output"
155 CAPS="$CAPS --cap $f"
164 if [ "$1" = "--silent" ] ; then
171 # Setup the default ulimit for a vserver
173 # File handle are limited to half of the current system limit
174 # Virtual memory is limited to the ram size
175 NFILE=`cat /proc/sys/fs/file-max`
176 NFILE=`expr $NFILE / 2`
177 VMEM=`cat /proc/meminfo | grep MemTotal | (read a b c; echo $b)`
178 # Disabled for now, we need a different to set the security
179 # context limit than fiddling with ulimit
180 #ulimit -H -n $NFILE -v $VMEM
182 if [ $# -lt 2 ] ; then
184 elif [ "$2" = "build" ] ; then
185 # Either the directory does not exist or is empty
186 NBSUB=`ls $VROOTDIR/$1 2>/dev/null | grep -v lost+found | wc -l`
188 if [ "$NBSUB" != 0 ] ; then
189 echo Virtual server $VROOTDIR/$1 already exist
191 if [ ! -d $VROOTDIR ] ; then
192 mkdir $VROOTDIR || exit 1
195 echo Directory $VROOTDIR was created with permissions 000
197 mkdir -p $VROOTDIR/$1 || exit 1
198 chattr -t $VROOTDIR/$1
199 chmod 755 $VROOTDIR/$1
200 if test "$UTIL_VSERVER_AVOID_COPY"; then
201 mkdir -p $VROOTDIR/$1/{etc/rc.d/init.d,sbin,var/run,var/log}
203 cp -ax /sbin /bin /etc /usr /var /lib $VROOTDIR/$1/. || exit 1
205 cd $VROOTDIR/$1 || exit 1
207 rm -f var/spool/mail/*
208 rm -f `find var/run -type f`
209 rm -f `find var/log -type f`
211 rm -f var/lock/subsys/*
212 rm -f etc/cron.d/kmod
213 mkdir proc tmp home root boot
214 test -f /root/.bashrc && cp -a /root/.bashrc root/.
215 test -f /root/.bash_profile && cp -a /root/.bash_profile root/.
218 # Create a minimal dev so the virtual server can't grab
221 vserver_mknod dev/null c 1 3 666
222 vserver_mknod dev/zero c 1 5 666
223 vserver_mknod dev/full c 1 7 666
224 vserver_mknod dev/random c 1 8 644
225 vserver_mknod dev/urandom c 1 9 644
226 vserver_mknod dev/tty c 5 0 666
227 vserver_mknod dev/ptmx c 5 2 666
229 # Create a dummy /etc/fstab and /etc/mtab to please
230 # df and linuxconf. We use hdv1, which does not exist
231 # to remind the admin that it is not the real drive
232 echo /dev/hdv1 / ext2 defaults 1 1 >etc/fstab
233 echo /dev/hdv1 / ext2 rw 0 0 >etc/mtab
234 # Install the vreboot utility
235 cp -a $USR_LIB_VSERVER/vreboot sbin/.
236 ln -sf vreboot sbin/vhalt
238 echo Directory $VROOTDIR/$1 has been populated
239 if [ ! -d /etc/vservers ] ; then
241 chmod 600 /etc/vservers
242 echo Directory /etc/vservers has been created
244 if [ ! -f /etc/vservers/$1.conf ] ; then
245 CONF=/etc/vservers/$1.conf
247 if [ "$PROFILE" = "" ] ; then
250 # Select the IP number assigned to the virtual server
251 # This IP must be one IP of the server, either an interface
253 # A vserver may have more than one IP. Separate them with spaces.
254 # do not forget double quotes.
256 # IPROOT="1.2.3.4 2.3.4.5"
257 # IPROOT="eth0:1.2.3.4 eth1:2.3.4.5"
258 # If the device is not specified, IPROOTDEV is used
262 # The netmask and broadcast are computed by default from IPROOTDEV
265 # You can define on which device the IP alias will be done
266 # The IP alias will be set when the server is started and unset
267 # when the server is stopped
269 # You can set a different host name for the vserver
270 # If empty, the host name of the main server is used
281 # Uncomment the onboot line if you want to enable this
282 # virtual server at boot time
284 # You can set a different NIS domain for the vserver
285 # If empty, the current on is kept
286 # Set it to "none" to have no NIS domain set
288 # You can set the priority level (nice) of all process in the vserver
289 # Even root won't be able to raise it
291 # You can set various flags for the new security context
292 # lock: Prevent the vserver from setting new security context
293 # sched: Merge scheduler priority of all processes in the vserver
294 # so that it acts a like a single one.
295 # nproc: Limit the number of processes in the vserver according to ulimit
296 # (instead of a per user limit, this becomes a per vserver limit)
297 # private: No other process can join this security context. Even root
298 # Do not forget the quotes around the flags
300 # You can set various ulimit flags and they will be inherited by the
301 # vserver. You enter here various command line argument of ulimit
302 # ULIMIT="-HS -u 200"
303 # The example above, combined with the nproc S_FLAGS will limit the
304 # vserver to a maximum of 200 processes
306 # You can set various capabilities. By default, the vserver are run
307 # with a limited set, so you can let root run in a vserver and not
308 # worry about it. He can't take over the machine. In some cases
309 # you can to give a little more capabilities (such as CAP_NET_RAW)
310 # S_CAPS="CAP_NET_RAW"
312 # Select an unused context (this is optional)
313 # The default is to allocate a free context on the fly
314 # In general you don't need to force a context
317 echo $CONF has been created. Look at it\!
319 # Turn off some service useless on a vserver
320 # vserver_turnoff apmd network autofs dhcpd gpm ipchains iptables \
321 # irda isdn keytable kudzu linuxconf-setup netfs nfs nfslock \
322 # pcmcia portmap pppoe random rawdevices rhnsd rstatd ruserd \
323 # rwalld rwhod sendmail smb snmpd v_httpd h_xinetd v_sshd vservers \
326 cd etc/init.d 2>/dev/null || cd etc/rc.d/init.d
330 *.bak|*~|functions|killall|halt|single)
333 #$USR_LIB_VSERVER/capchroot $VROOTDIR/$1 /sbin/chkconfig --level 2345 $serv off
334 $0 --silent $1 chkconfig --level 2345 $serv off
339 rm -f etc/rc.d/rc6.d/S*reboot
341 elif [ ! -f /etc/vservers/$1.conf ] ; then
342 echo No configuration for this vserver: /etc/vservers/$1.conf
344 elif [ ! -d $VROOTDIR/$1/. ] ; then
345 echo No directory for this vserver: $VROOTDIR/$1
347 elif [ "$2" = "start" ] ; then
348 echo Starting the virtual server $1
350 if ! $VSERVER_CMD $1 running
352 test -x /etc/vservers/$1.sh && /etc/vservers/$1.sh pre-start $1
355 . /etc/vservers/$1.conf
357 cd $VROOTDIR/$1 || exit 1
359 if [ "$PROFILE" != "" ] ; then
360 echo export PROFILE=$PROFILE >etc/PROFILE
363 rm -f `find var/run -type f`
365 chgrp ${UTMP_GROUP:-utmp} var/run/utmp
366 chmod 0664 var/run/utmp
367 rm -f var/lock/subsys/*
368 mountproc $VROOTDIR/$1
376 STARTCMD="/etc/rc.d/rc $INITDEFAULT"
377 if [ -x $VROOTDIR/$1/etc/init.d/rc ] ; then
378 STARTCMD="/etc/init.d/rc $INITDEFAULT"
379 elif [ -x $VROOTDIR/$1/usr/bin/emerge ] ; then
380 STARTCMD="/sbin/rc default"
381 elif [ -x $VROOTDIR/$1/etc/rc.d/rc.M ] ; then
382 STARTCMD="/etc/rc.d/rc.M"
387 for f in $S_FLAGS dummy
395 FLAGS="$FLAGS --flag fakeinit"
396 STARTCMD=/sbin/minit-start
397 DISCONNECT=--disconnect
402 FLAGS="$FLAGS --flag $f"
404 DISCONNECT=--disconnect
407 FLAGS="$FLAGS --flag $f"
411 if [ -n "$S_START" ] ; then
414 if [ "$FAKEINIT" = "" ] ; then
415 $USR_LIB_VSERVER/fakerunlevel $INITDEFAULT var/run/utmp
418 calculateCaps $S_CAPS
420 if [ "$S_CONTEXT" != "" ] ; then
421 CTXOPT="--ctx $S_CONTEXT"
423 if [ "$S_HOSTNAME" != "" ] ; then
424 HOSTOPT="--hostname $S_HOSTNAME"
425 export HOSTNAME=$S_HOSTNAME
427 if [ "$S_DOMAINNAME" != "" ] ; then
428 DOMAINOPT="--domainname $S_DOMAINNAME"
430 if [ "$S_NICE" != "" ] ; then
431 NICECMD="nice -$S_NICE"
433 mkdir -p /var/run/vservers
434 chmod 700 /var/run/vservers
436 if [ "$ULIMIT" != "" ] ; then
441 # We switch to $VROOTDIR/$1 now, because after the
442 # security context switch $VROOTDIR directory becomes a dead zone.
444 export PATH=$DEFAULTPATH
445 # XXX execute /etc/rc.vinit first for backward compatibility
446 for CMD in "$VINIT_CMD $2" "$STARTCMD" ; do
447 $WAITFOR_CMD $NICECMD \
448 $CHCONTEXT_CMD $SILENT $DISCONNECT $CAPS $FLAGS $CTXOPT $HOSTOPT $DOMAINOPT --secure \
449 $SAVE_S_CONTEXT_CMD /var/run/vservers/$1.ctx \
450 $CAPCHROOT_CMD $CHROOTOPT . $CMD
453 test -x /etc/vservers/$1.sh && /etc/vservers/$1.sh post-start $1
455 elif [ "$2" = "running" ] ; then
456 if [ ! -f /var/run/vservers/$1.ctx ] ; then
457 echo Server $1 is not running
460 . /var/run/vservers/$1.ctx
461 NB=$($USR_SBIN/vps ax | awk '{print $2}' | grep \^$S_CONTEXT\$ | wc -l)
462 #NB=`$CHCONTEXT_CMD --silent --ctx $S_CONTEXT ps ax | wc -l`
463 #NB=`eval expr $NB + 0`
464 if [ "$NB" -gt 0 ] ; then
465 echo Server $1 is running
468 echo Server $1 is not running
472 elif [ "$2" = "status" ] ; then
475 . /var/run/vservers/$1.ctx
476 NB=$($USR_SBIN/vps ax | awk '{print $2}' | grep \^$S_CONTEXT\$ | wc -l)
477 echo $NB processes running
478 echo Vserver uptime: `$USR_LIB_VSERVER/filetime /var/run/vservers/$1.ctx`
480 elif [ "$2" = "stop" ] ; then
481 echo Stopping the virtual server $1
485 if $VSERVER_CMD $1 running
487 test -x /etc/vservers/$1.sh && /etc/vservers/$1.sh pre-stop $1
489 mountproc $VROOTDIR/$1
490 # The fakeinit flag tell us how to turn off the server
492 export PREVLEVEL=$INITDEFAULT
493 STOPCMD="/etc/rc.d/rc 6"
494 if [ -x $VROOTDIR/$1/etc/init.d/rc ] ; then
495 STOPCMD="/etc/init.d/rc 6"
496 elif [ -x $VROOTDIR/$1/usr/bin/emerge ] ; then
497 STOPCMD="/sbin/rc shutdown"
498 elif [ -x $VROOTDIR/$1/etc/rc.d/rc.6 ] ; then
499 STOPCMD="/etc/rc.d/rc.6"
502 for f in $S_FLAGS dummy
507 FLAGS="$FLAGS --flag fakeinit"
508 STOPCMD="/sbin/minit-stop"
512 FLAGS="$FLAGS --flag $f"
513 STOPCMD="/sbin/init 6"
520 if [ -n "$S_STOP" ] ; then
524 calculateCaps $S_CAPS
527 export PATH=$DEFAULTPATH
528 # XXX execute /etc/rc.vinit first for backward compatibility
529 for CMD in "$VINIT_CMD $2" "$STOPCMD" ; do
530 $WAITFOR_CMD $CHCONTEXT_CMD $SILENT $CAPS --secure --ctx $S_CONTEXT \
531 $CAPCHROOT_CMD . $CMD
534 if test "$IS_MINIT"; then
535 echo "Waiting for minit finish-signal"
536 dd if=var/run/minit-stop of=/dev/zero bs=1 count=1 &>/dev/null
539 echo sleeping 5 seconds
543 echo Killing all processes
544 $CHCONTEXT_CMD $CAPS --secure --silent --ctx $S_CONTEXT \
547 # We umount anyway, because "enter" establish the mount
548 # but when you exit, the server is considered not running
549 umountproc $VROOTDIR/$1
551 test -x /etc/vservers/$1.sh && /etc/vservers/$1.sh post-stop $1
552 elif [ "$2" = "restart" ] ; then
558 elif [ "$2" = "suexec" ] ; then
559 if [ -z "$3" ] ; then
560 echo "Missing user!" >&2
561 echo "vserver vserver-name suexec user command [ args ... ]" >&2
563 elif [ -z "$4" ] ; then
564 echo "Missing command and arguments!" >&2
565 echo "vserver vserver-name suexec user command [ args ... ]" >&2
569 . /etc/vservers/$1.conf
571 mountproc $VROOTDIR/$1
572 PS1="[\u@vserver:$1 \W]"
578 for f in $S_CAPS dummy
587 CAPS="$CAPS --cap $f"
592 for f in $S_FLAGS dummy
596 FLAGS="$FLAGS --flag fakeinit"
602 FLAGS="$FLAGS --flag $f"
607 if [ "$ULIMIT" != "" ] ; then
610 if $0 $VSERVER running >/dev/null
612 . /var/run/vservers/$VSERVER.ctx
613 cd $VROOTDIR/$VSERVER
614 export PATH=$DEFAULTPATH
615 exec $CHCONTEXT_CMD $SILENT $FLAGS $CAPS --secure --ctx $S_CONTEXT \
616 $CAPCHROOT_CMD --suid $USERID . "$@"
618 test -x /etc/vservers/$1.sh && /etc/vservers/$1.sh pre-start $1
622 if [ "$S_CONTEXT" != "" ] ; then
623 CTXOPT="--ctx $S_CONTEXT"
625 if [ "$S_HOSTNAME" != "" ] ; then
626 HOSTOPT="--hostname $S_HOSTNAME"
627 export HOSTNAME=$S_HOSTNAME
629 if [ "$S_DOMAINNAME" != "" ] ; then
630 DOMAINOPT="--domainname $S_DOMAINNAME"
632 mkdir -p /var/run/vservers
633 cd $VROOTDIR/$VSERVER
634 export PATH=$DEFAULTPATH
635 exec $CHCONTEXT_CMD $SILENT $FLAGS $CAPS --secure $CTXOPT $HOSTOPT $DOMAINOPT \
636 $SAVE_S_CONTEXT_CMD /var/run/vservers/$VSERVER.ctx \
637 $CAPCHROOT_CMD --suid $USERID $CHROOTOPT . "$@"
640 elif [ "$2" = "exec" ] ; then
643 exec $0 $SILENT $VSERV suexec root "$@"
644 elif [ "$2" = "enter" ] ; then
646 exec $0 $SILENT $1 exec /bin/bash -login
647 elif [ "$2" = "service" ] ; then
651 exec $0 $SILENT $VSERVER exec /sbin/service "$@"
652 elif [ "$2" = "chkconfig" ] ; then
657 if [ "$1" = "--level" ] ; then
658 LEVELS=( --level "$2" )
661 if [ $# != 2 -a ! -x $VROOTDIR/$VSERVER/sbin/chkconfig ] ; then
662 echo Invalid argument, expected vserver name chkconfig [ --level nnn ] service on\|off
663 elif [ -x $VROOTDIR/$VSERVER/sbin/chkconfig ] ; then
664 exec $0 --silent $VSERVER exec /sbin/chkconfig "${LEVELS[@]}" "$@"
665 elif [ -x $VROOTDIR/$VSERVER/usr/sbin/update-rc.d ] ; then
666 if [ "$2" = "on" -o "$2" = "start" ] ; then
667 $0 --silent $VSERVER exec /usr/sbin/update-rc.d -f $1 remove >/dev/null
668 exec $0 --silent $VSERVER exec /usr/sbin/update-rc.d $1 start 80 2 3 4 5 . stop 20 0 1 6 . >/dev/null
669 elif [ "$2" = "off" -o "$2" = "stop" ] ; then
670 $0 --silent $VSERVER exec /usr/sbin/update-rc.d -f $1 remove >/dev/null
671 exec $0 --silent $VSERVER exec /usr/sbin/update-rc.d $1 stop 20 0 1 2 3 4 5 6 . >/dev/null
673 echo vserver chkconfig: Expecting on or off
676 echo chkconfig functionality is not available on this
677 echo vserver distribution.
678 echo Looked for /sbin/chkconfig and /usr/sbin/update-rc.d
681 echo Command unknown $2