chroot 环境下让普通用户修改配置文件
6月 26th, 2008 Posted in shell < by Martian Guo >
以前写的一个脚本,因为有一个项目要求让普通用户修改一些配置文件,而不能让他们有root权限。首先想到的是给这个用户sudo 权限用来执行一个脚本调用vi编辑器,而在vi中是可以直接调用系统命令的,因此这样做并不可靠。我想到了在脚本控制下给vi编辑器一个chroot环境,当vi修改完配置文件后,通过脚本控制复制到实际路径中替换掉旧文件并且可以备份每次修改的diff。下面是我写的一个脚本。介绍一下:
首先设置一个vi的chroot环境,主要程序文件,实际vim依赖哪些so可以用命令 ldd vim 来获取到,可以从相应实际目录中拷贝过来。
./
./bin
./bin/vim
./tmp
./etc
./etc/vimrc
./lib
./lib/ld-linux.so.2
./lib/libdl.so.2
./lib/libselinux.so.1
./lib/libgpm.so.1
./lib/libattr.so.1
./lib/libnsl.so.1
./lib/libc.so.6
./lib/libpthread.so.0
./lib/libncurses.so.5
./lib/libresolv.so.2
./lib/libacl.so.1
./lib/libcrypt.so.1
./lib/libperl.so
./lib/libtermcap.so.2
./lib/libm.so.6
./lib/libutil.so.1
./root
./root/.viminfo
./bin
./bin/vim
./tmp
./etc
./etc/vimrc
./lib
./lib/ld-linux.so.2
./lib/libdl.so.2
./lib/libselinux.so.1
./lib/libgpm.so.1
./lib/libattr.so.1
./lib/libnsl.so.1
./lib/libc.so.6
./lib/libpthread.so.0
./lib/libncurses.so.5
./lib/libresolv.so.2
./lib/libacl.so.1
./lib/libcrypt.so.1
./lib/libperl.so
./lib/libtermcap.so.2
./lib/libm.so.6
./lib/libutil.so.1
./root
./root/.viminfo
下面是脚本,主要功能:自动搜索特定目录下的文件,修改后自动备份和随时回滚的功能,脚本写的很简单,没什么可说的。当然,你肯定又会说了,何必这么麻烦呢,直接把那些配置文件的修改权给这个用户不就好了吗?如果你非要这样也我也没有办法,这里只是提供这样一种方法,到底要怎么实现怎么做要看具体情况。
#!/bin/sh
#################################################
# File edit&backup&restore tools for sudo user #
# martian <martian2008@gmail.com> #
#################################################
if [ "$UID" != 0 ];then
echo access denied
exit 1
fi
chroot="/usr/local/chroot_vim" # chroot环境路径
backup="/usr/local/configfile_back" # 备份文件保存目录
path=(/usr/local/tomcat6/conf /usr/local/httpd/conf /usr/local/php/etc)
# 有权限修改配置文件的目录
USAGE="Usage: `basename $0` [OPTION]... {FileName} \n -e Edit File \n \
-r Restore File \n"
if [ "$#" -eq 0 ] ;then
echo -e "${USAGE}"
exit 1
fi
get_char()
{
SAVEDSTTY=`stty -g`
stty -echo
stty raw
dd if=/dev/tty bs=1 count=1 2> /dev/null
stty -raw
stty echo
stty $SAVEDSTTY
}
answer()
{
ANSWER=""
while [[ "$ANSWER" != "y" ]] && [[ "$ANSWER" != "Y" ]]
do
echo -en "Do you want to "
echo -en "\\033[0;35m"
echo -en "$info"
echo -en "\\033[0;38m"
echo " this File? (y/n)"
read ANSWER
case $ANSWER in
(y|Y) return 0 ;;
(n|N) return 1 ;;
*)continue;
esac
done
}
select_diff()
{
N=""
read N
until [[ $N =~ ^[0-9]+$ ]] # bash 3.0
do
echo -n "Please type one number:"
read N
done
}
while getopts e:r: OPTION;
do
case "$OPTION" in
e) info="Edit"
F="$OPTARG";;
r) info="Restore"
F="$OPTARG";;
\?) echo -e $USEAGE
exit 1
esac
done
if [ -n "$F" ];then
for filedir in ${path[*]}
do
for f in `/usr/bin/find "$filedir" -type f -name "$F"`
do
echo
echo -en "\\033[0;35m"
echo -en "$info"
echo -en "\\033[0;38m"
echo -en " File "
echo -en "\\033[0;36m"
echo "$f ..."
echo -en "\\033[0;38m"
answer
if [ "$?" == 0 ];then
filename="`echo "$f" |sed 's#/#\|#g'`"
if [ "$info" == "Restore" ];then
f1=(`/usr/bin/find "$backup"/"$filename".diff.* -xdev 2>/dev/null `)
echo -ne "Found "
echo -ne "\\033[0;35m"
echo -ne ${#f1[*]}
echo -ne "\\033[0;38m"
echo " Diff File"
if [ "${#f1[*]}" == 0 ];then
echo "Skip..."
else
i=${#f1[*]}
for f4 in ${f1[*]}
do
echo -ne "`/bin/basename $f4` "
echo `ls -l "$f4" |awk '{print $6, $7, $8}'`
done
echo -n "Please type one number to Restore [ ${#f1[*]}-1 ]:"
select_diff
echo -ne "Your Select "
echo -ne "\\033[0;35m"
echo -ne "$N"
echo -ne "\\033[0;38m"
echo " to Restore"
pushd "`/usr/bin/dirname $f`" >/dev/null
until [ $N -gt $i ]
do
i=$((i-1))
echo "Process File ${f1[$i]}......"
/usr/bin/patch <${f1[$i]}
if [ "$?" == 0 ];then
/bin/rm ${f1[$i]}
fi
done
popd >/dev/null 2>&1
fi
else
/bin/cp -a "$f" "$chroot"/tmp/"$filename"
/usr/sbin/chroot "$chroot" /bin/vim /tmp/"$filename"
/usr/bin/diff -Nu "$chroot"/tmp/"$filename" "$f" \
>"$chroot"/tmp/"$filename".diff
if [ "$?" != 0 ];then
echo -n "Backup Confilg File..."
f2="$backup"/"$filename".diff
f1=(`/usr/bin/find $f2.* -xdev 2>/dev/null `)
i=${#f1[*]}
i=$((i+1))
echo $i
/bin/mv "$chroot"/tmp/"$filename".diff "$f2".$i
echo done
echo -n "Saveing... Press any key to continue..."
/bin/cp -a "$chroot"/tmp/"$filename" "$f"
echo done
char=`get_char`
fi
fi
fi
done
done
fi
#################################################
# File edit&backup&restore tools for sudo user #
# martian <martian2008@gmail.com> #
#################################################
if [ "$UID" != 0 ];then
echo access denied
exit 1
fi
chroot="/usr/local/chroot_vim" # chroot环境路径
backup="/usr/local/configfile_back" # 备份文件保存目录
path=(/usr/local/tomcat6/conf /usr/local/httpd/conf /usr/local/php/etc)
# 有权限修改配置文件的目录
USAGE="Usage: `basename $0` [OPTION]... {FileName} \n -e Edit File \n \
-r Restore File \n"
if [ "$#" -eq 0 ] ;then
echo -e "${USAGE}"
exit 1
fi
get_char()
{
SAVEDSTTY=`stty -g`
stty -echo
stty raw
dd if=/dev/tty bs=1 count=1 2> /dev/null
stty -raw
stty echo
stty $SAVEDSTTY
}
answer()
{
ANSWER=""
while [[ "$ANSWER" != "y" ]] && [[ "$ANSWER" != "Y" ]]
do
echo -en "Do you want to "
echo -en "\\033[0;35m"
echo -en "$info"
echo -en "\\033[0;38m"
echo " this File? (y/n)"
read ANSWER
case $ANSWER in
(y|Y) return 0 ;;
(n|N) return 1 ;;
*)continue;
esac
done
}
select_diff()
{
N=""
read N
until [[ $N =~ ^[0-9]+$ ]] # bash 3.0
do
echo -n "Please type one number:"
read N
done
}
while getopts e:r: OPTION;
do
case "$OPTION" in
e) info="Edit"
F="$OPTARG";;
r) info="Restore"
F="$OPTARG";;
\?) echo -e $USEAGE
exit 1
esac
done
if [ -n "$F" ];then
for filedir in ${path[*]}
do
for f in `/usr/bin/find "$filedir" -type f -name "$F"`
do
echo
echo -en "\\033[0;35m"
echo -en "$info"
echo -en "\\033[0;38m"
echo -en " File "
echo -en "\\033[0;36m"
echo "$f ..."
echo -en "\\033[0;38m"
answer
if [ "$?" == 0 ];then
filename="`echo "$f" |sed 's#/#\|#g'`"
if [ "$info" == "Restore" ];then
f1=(`/usr/bin/find "$backup"/"$filename".diff.* -xdev 2>/dev/null `)
echo -ne "Found "
echo -ne "\\033[0;35m"
echo -ne ${#f1[*]}
echo -ne "\\033[0;38m"
echo " Diff File"
if [ "${#f1[*]}" == 0 ];then
echo "Skip..."
else
i=${#f1[*]}
for f4 in ${f1[*]}
do
echo -ne "`/bin/basename $f4` "
echo `ls -l "$f4" |awk '{print $6, $7, $8}'`
done
echo -n "Please type one number to Restore [ ${#f1[*]}-1 ]:"
select_diff
echo -ne "Your Select "
echo -ne "\\033[0;35m"
echo -ne "$N"
echo -ne "\\033[0;38m"
echo " to Restore"
pushd "`/usr/bin/dirname $f`" >/dev/null
until [ $N -gt $i ]
do
i=$((i-1))
echo "Process File ${f1[$i]}......"
/usr/bin/patch <${f1[$i]}
if [ "$?" == 0 ];then
/bin/rm ${f1[$i]}
fi
done
popd >/dev/null 2>&1
fi
else
/bin/cp -a "$f" "$chroot"/tmp/"$filename"
/usr/sbin/chroot "$chroot" /bin/vim /tmp/"$filename"
/usr/bin/diff -Nu "$chroot"/tmp/"$filename" "$f" \
>"$chroot"/tmp/"$filename".diff
if [ "$?" != 0 ];then
echo -n "Backup Confilg File..."
f2="$backup"/"$filename".diff
f1=(`/usr/bin/find $f2.* -xdev 2>/dev/null `)
i=${#f1[*]}
i=$((i+1))
echo $i
/bin/mv "$chroot"/tmp/"$filename".diff "$f2".$i
echo done
echo -n "Saveing... Press any key to continue..."
/bin/cp -a "$chroot"/tmp/"$filename" "$f"
echo done
char=`get_char`
fi
fi
fi
done
done
fi