Skip to content

Instantly share code, notes, and snippets.

@shellexy
Last active January 6, 2018 13:57
Show Gist options
  • Select an option

  • Save shellexy/71fbf233a2d42d27c23f357df061a534 to your computer and use it in GitHub Desktop.

Select an option

Save shellexy/71fbf233a2d42d27c23f357df061a534 to your computer and use it in GitHub Desktop.
使用文件系统镜像来实现文件夹容量限额
#!/bin/bash
## 使用文件系统镜像来实现文件夹容量限额
help()(
echo "设置目录限额
用法:
quota 添加一个限额目录
list 列出限额的目录
unquota 某目录不再限额
quit 退出程序
"
)
quota()(
## 使用文件系统镜像来实现文件夹容量限额
quota_dir="$1"
quota_size="$2"
## 提示输入 quota_dir quota_size
test -n "$quota_dir" || read -e -i "quota_dir" -p "请输入要限制总容量大小的文件夹名字: " quota_dir
test -n "$quota_size" && test "$quota_size" -gt 1 || read -e -i "50" -p "请输入文件夹限制大小(单位 M): " quota_size
## 用 test "$quota_size" -gt 1 来验证 quota_size 的数字大于 1
test -n "$quota_dir" && test "$quota_size" -gt 1 || {
echo "用法: quota 目录名 限额大小"
exit
}
quota_dir=$(readlink -f "$quota_dir")
quota_mnt="$quota_dir"
## 镜像文件名 为在 quota_dir 目录下的 .quota.img
quota_img="$quota_dir/.quota.img"
echo "将把文件夹 '$quota_dir' 限额为 $quota_size MB,文件夹内原有文件会被隐藏"
## 因为使用文件系统镜像会损失一点容量,所以将原有容量 x 1.1
quota_size=$[quota_size*11/10]
mkdir -p "$quota_mnt"
## @TODO 在已经存在镜像文件,但是限额大小不一样的情况下,需要重设大小
## 如果目录下已经有镜像文件,则先尝试挂载原有镜像文件
test -a "$quota_img" && {
echo "限额目录下已经存在限额用镜像文件,先尝试挂载使用"
mount -o loop "$quota_img" "$quota_mnt" || {
read -e -p "无法挂载现有镜像文件,您是否要初始化镜像文件?[Y/N]" IS_MKFS
test "$IS_MKFS" = "Y" -o "$IS_MKFS" = "y" || {
echo "您取消了初始化,退出目录限额操作"
exit
}
}
}
## 创建镜像文件
echo "初始化限额镜像文件…"
dd if=/dev/zero of="$quota_img" bs=1M count="$quota_size"
mkfs.ext4 -m 0 "$quota_img"
## 将镜像文件挂载为 限额目录
mount -o loop "$quota_img" "$quota_mnt" || {
echo "无法挂载限额用镜像文件,退出目录限额操作"
exit
}
## 写入 fstab
fstab="/etc/fstab"
sed -i "/${quota_img//\//\\/}/d" /etc/fstab
fstab_line="$quota_img $quota_mnt ext4 loop 0 0"
echo "$fstab_line" >> /etc/fstab
echo -e "在 /etc/fstab 增加了一行\n$fstab_line\n解除限额时将删掉该行"
)
list()(
## 从 /etc/fstab 里列出限额了的目录名字
dirs="`grep -E '\.quota\.img.*loop' /etc/fstab | awk '{print $2}'`"
echo -e "$dirs \n"
test -n "$dirs" && df -h $dirs
)
unquota()(
echo "以下目录已经限额:"
list
read -e -p "您希望对哪个目录解除限额:" quota_dir
quota_dir=$(readlink -f "$quota_dir")
quota_img="$quota_dir/.quota.img"
test -e "$quota_dir" && grep -q "$quota_img" /etc/fstab || {
echo "限额的目录里没有找到您输入的 '$quota_dir'"
exit
}
read -e -i "N" -p "您是否确认解除目录 '$quota_dir' 的限额?[Y/N]" IS_UNQUOTA
echo "$IS_UNQUOTA" | grep -q -E '^[Yy]$' || exit
## 卸载镜像,并修改 /etc/fstab 里的限额记录
umount -f "$quota_dir" && sed -i "/${quota_img//\//\\/}/d" /etc/fstab || {
echo "解除失败"
exit
}
## 之前是使用镜像文件来实现限额,所以解除限额时 询问是否将限额期间的内容回写进原目录
read -e -i "Y" -p "是否将镜像文件里的内容写回原有目录?[Y/N]" IS_WRITEBACK
echo "$IS_WRITEBACK" | grep -q -E '^[Yy]$' && {
tmp_dir="$quota_dir/.quota.dir"
mkdir -p "$tmp_dir"
mount -o loop "$quota_img" "$tmp_dir" &&
rsync -u -h -a -A -X -S --progress --exclude=lost+found "$tmp_dir/." "$quota_dir" && {
echo "已经成功写回 '$quota_dir'"
} || {
echo "回写失败"
}
sync
umount -f "$tmp_dir" && rmdir "$tmp_dir"
}
## 删除限额用镜像
read -e -i "N" -p "是否删除限额用过的镜像文件?[Y/N]" IS_DEL
echo "$IS_DEL" | grep -q -E '^[Yy]$' && {
rm -v "$quota_img"
}
##
echo "已经解除了目录 '$quota_dir' 的限额,目前依然限额的目录为:"
list
)
help ##帮助
while true; do
[ -z "$HELPED" ] && echo '查看帮助请输入 help'
HELPED=1
read -e -p '请选择命令> ' CMD
[ "$CMD" = quit ] && exit
[ "$CMD" = q ] && exit
## 检测输入的命令有没有存在对应函数
test -z "$CMD" && continue ## 输入命令为空
type -t "$CMD" | grep -q function || {
echo "命令 $CMD 没找到,查看帮助请输入 help"
continue
}
## 测试模式下不实际执行命令,而是显示命令内容
if [ -n "$TEST" ] ; then
type "$CMD"
else
"$CMD"
fi
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment