#!/bin/bash
# 颜色
Green="\033[32m"
Yellow="\033[33m"
Red="\033[31m"
GreenBG="\033[42;37m"
YellowBG="\033[43;37m"
RedBG="\033[41;37m"
Font="\033[0m"
# 通知信息
OK="${Green}[OK]${Font}"
Warn="${Yellow}[警告]${Font}"
Error="${Red}[错误]${Font}"
# 基本参数
WORK_DIR="$(pwd)"
INPUT_ARGS=$@
COMPOSE="docker-compose"
# 缓存执行
if [ -z "$CACHED_EXECUTION" ] && [ "$1" == "update" ]; then
if ! cat "$0" > ._cmd 2>/dev/null; then
error "无法创建脚本副本"
exit 1
fi
chmod +x ._cmd
export CACHED_EXECUTION=1
./._cmd "$@"
EXIT_STATUS=$?
rm -f ._cmd
exit $EXIT_STATUS
fi
# 判断是否成功
judge() {
if [[ 0 -eq $? ]]; then
success "$1 完成"
sleep 1
else
error "$1 失败"
exit 1
fi
}
# 执行并判断是否成功
exec_judge() {
local cmd="$1"
local error_desc="$2"
local success_desc="$3"
eval "$cmd"
if [[ 0 -ne $? ]]; then
error "$error_desc"
exit 1
fi
if [[ -n "$success_desc" ]]; then
success "$success_desc"
fi
}
# 输出成功
success() {
echo -e "${OK} ${GreenBG}$1${Font}"
}
# 输出警告
warning() {
echo -e "${Warn} ${YellowBG}$1${Font}"
}
# 输出错误
error() {
echo -e "${Error} ${RedBG}$1${Font}"
}
# 随机数
rand() {
local min=$1
local max=$(($2-$min+1))
local num=$(($RANDOM+1000000000))
echo $(($num%$max+$min))
}
# 随机字符串
rand_string() {
local lan=$1
if [[ `uname` == 'Linux' ]]; then
echo "$(date +%s%N | md5sum | cut -c 1-${lan})"
else
echo "$(docker run -it --rm nginx:alpine sh -c "date +%s%N | md5sum | cut -c 1-${lan}")"
fi
}
# 重启php
restart_php() {
local RES=`container_exec php "supervisorctl update php"`
if [ -z "$RES" ]; then
RES=`container_exec php "supervisorctl restart php"`
fi
local IN=`echo $RES | grep "ERROR"`
if [[ "$IN" != "" ]]; then
$COMPOSE stop php
$COMPOSE start php
else
echo "$RES"
fi
}
# 切换调试模式
switch_debug() {
local debug="false"
if [[ "$1" == "true" ]] || [[ "$1" == "dev" ]] || [[ "$1" == "open" ]]; then
debug="true"
fi
if [[ "$(env_get APP_DEBUG)" != "$debug" ]]; then
env_set APP_DEBUG "$debug"
restart_php
fi
}
# 检查是否有sudo
check_sudo() {
if [ "$EUID" -ne 0 ]; then
error "请使用 sudo 运行此脚本"
exit 1
fi
}
# 检查docker、docker-compose
check_docker() {
docker --version &> /dev/null
if [ $? -ne 0 ]; then
error "未安装 Docker!"
exit 1
fi
docker-compose version &> /dev/null
if [ $? -ne 0 ]; then
docker compose version &> /dev/null
if [ $? -ne 0 ]; then
error "未安装 Docker-compose!"
exit 1
fi
COMPOSE="docker compose"
fi
if [[ -n `$COMPOSE version | grep -E "\s+v1\."` ]]; then
$COMPOSE version
error "Docker-compose 版本过低,请升级至v2+!"
exit 1
fi
}
# 检查node
check_node() {
npm --version &> /dev/null
if [ $? -ne 0 ]; then
error "未安装 npm!"
exit 1
fi
node --version &> /dev/null
if [ $? -ne 0 ]; then
error "未安装 Node.js!"
exit 1
fi
if [[ -n `node --version | grep -E "v1"` ]]; then
node --version
error "Node.js 版本过低,请升级至v20+!"
exit 1
fi
}
# 获取容器名称
docker_name() {
echo `$COMPOSE ps | awk '{print $1}' | grep "\-$1\-"`
}
# 编译前端
web_build() {
local type=$1
check_node
if [ ! -d "./node_modules" ]; then
npm install
fi
if [ "$type" = "dev" ]; then
echo "" > ./index.html
if [ -z "$(env_get APP_DEV_PORT)" ]; then
env_set APP_DEV_PORT $(rand 20001 30000)
fi
if [ -n "${VSCODE_PROXY_URI:-}" ]; then
APP_REAL_URI=$(TARGET_PORT="$(env_get APP_PORT)" node -p "process.env.VSCODE_PROXY_URI.replace(/\{\{port\}\}/g, process.env.TARGET_PORT || '')")
VSCODE_PROXY_URI=$(APP_DEV_PORT="$(env_get APP_DEV_PORT)" node -p "process.env.VSCODE_PROXY_URI.replace(/\{\{port\}\}/g, process.env.APP_DEV_PORT || '')")
echo "" > ./index.html
fi
env_set VSCODE_PROXY_URI "${VSCODE_PROXY_URI:-}"
fi
switch_debug "$type"
#
if [ "$type" = "prod" ]; then
rm -rf "./public/js/build"
npx vite build -- fromcmd
else
npx vite -- fromcmd
fi
}
# 运行electron
electron_operate() {
local argv=$@
check_node
if [ ! -d "./node_modules" ]; then
npm install
fi
if [ ! -d "./electron/node_modules" ]; then
pushd electron || exit
npm install
popd || exit
fi
#
if [ -d "./electron/dist" ]; then
rm -rf "./electron/dist"
fi
if [ -d "./electron/public" ]; then
rm -rf "./electron/public"
fi
#
BUILD_FRONTEND="build"
if [ "$argv" == "dev" ]; then
switch_debug "$argv"
BUILD_FRONTEND="dev"
fi
env BUILD_FRONTEND=$BUILD_FRONTEND node ./electron/build.js $argv
}
# 执行容器命令
container_exec() {
local container=$1
shift 1
local cmd=$@
local name=$(docker_name "$container")
if [ -z "$name" ]; then
error "没有找到 ${container} 容器!"
exit 1
fi
docker exec -it "$name" /bin/sh -c "$cmd"
}
# 备份数据库、还原数据库
mysql_snapshot() {
if [ "$1" = "backup" ]; then
database=$(env_get DB_DATABASE)
username=$(env_get DB_USERNAME)
password=$(env_get DB_PASSWORD)
# 备份数据库
mkdir -p ${WORK_DIR}/docker/mysql/backup
filename="${WORK_DIR}/docker/mysql/backup/${database}_$(date "+%Y%m%d%H%M%S").sql.gz"
container_exec mariadb "exec mysqldump --databases $database -u${username} -p${password}" | gzip > $filename
judge "备份数据库"
[ -f "$filename" ] && echo "备份文件:${filename}"
elif [ "$1" = "recovery" ]; then
database=$(env_get DB_DATABASE)
username=$(env_get DB_USERNAME)
password=$(env_get DB_PASSWORD)
# 还原数据库
mkdir -p ${WORK_DIR}/docker/mysql/backup
shopt -s nullglob
backup_files=("${WORK_DIR}/docker/mysql/backup/"*.sql.gz)
shopt -u nullglob
if [ ${#backup_files[@]} -eq 0 ]; then
error "没有备份文件!"
exit 1
fi
echo "可用备份列表:"
for idx in "${!backup_files[@]}"; do
printf "%2d) %s\n" "$((idx + 1))" "$(basename "${backup_files[$idx]}")"
done
while true; do
read -rp "请输入备份文件编号还原:" selection
if [[ "$selection" =~ ^[0-9]+$ ]] && [ "$selection" -ge 1 ] && [ "$selection" -le ${#backup_files[@]} ]; then
break
fi
warning "编号无效,请重新输入。"
done
filename="${backup_files[$((selection - 1))]}"
inputname="$(basename "$filename")"
container_name=`docker_name mariadb`
if [ -z "$container_name" ]; then
error "没有找到 mariadb 容器!"
exit 1
fi
docker cp "$filename" "${container_name}:/"
container_exec mariadb "gunzip < '/${inputname}' | mysql -u${username} -p${password} $database"
container_exec php "php artisan migrate"
judge "还原数据库"
fi
}
# 根据网络名称删除所有容器
remove_by_network() {
local app_id=$(env_get APP_ID)
local network_name="dootask-networks-${app_id}"
for container_id in $(docker ps -q --filter network="$network_name"); do
docker rm -f "$container_id" 1>/dev/null
done
}
# 自动配置https
https_auto() {
restart_nginx="n"
if [[ "$(env_get APP_PORT)" != "80" ]]; then
warning "HTTP服务端口不是80,是否修改并继续操作? [Y/n]"
read -r continue_http
[[ -z ${continue_http} ]] && continue_http="Y"
case $continue_http in
[yY][eE][sS] | [yY])
success "继续操作"
env_set "APP_PORT" "80"
restart_nginx="y"
;;
*)
error "操作终止"
exit 1
;;
esac
fi
if [[ "$(env_get APP_SSL_PORT)" != "443" ]]; then
warning "HTTPS服务端口不是443,是否修改并继续操作? [Y/n]"
read -r continue_https
[[ -z ${continue_https} ]] && continue_https="Y"
case $continue_https in
[yY][eE][sS] | [yY])
success "继续操作"
env_set "APP_SSL_PORT" "443"
restart_nginx="y"
;;
*)
error "操作终止"
exit 1
;;
esac
fi
if [[ "$restart_nginx" == "y" ]]; then
$COMPOSE up -d
fi
docker run -it --rm -v $(pwd):/work nginx:alpine sh /work/bin/https install
if [[ 0 -eq $? ]]; then
container_exec nginx "nginx -s reload"
fi
new_job="* 6 * * * docker run -it --rm -v $(pwd):/work nginx:alpine sh /work/bin/https renew"
current_crontab=$(crontab -l 2>/dev/null)
if ! echo "$current_crontab" | grep -v "https renew"; then
echo "任务已存在,无需添加。"
else
crontab -l |{
cat
echo "$new_job"
} | crontab -
echo "任务已添加。"
fi
}
# 获取env参数
env_get() {
local key=$1
local value=`cat ${WORK_DIR}/.env | grep "^$key=" | awk -F '=' '{print $2}' | tr -d '\r\n'`
echo "$value"
}
# 设置env参数
env_set() {
local key=$1
local val=$2
local exist=`cat ${WORK_DIR}/.env | grep "^$key="`
if [ -z "$exist" ]; then
echo "$key=$val" >> $WORK_DIR/.env
else
if [[ `uname` == 'Linux' ]]; then
sed -i "/^${key}=/c\\${key}=${val}" ${WORK_DIR}/.env
else
docker run -it --rm -v ${WORK_DIR}:/www nginx:alpine sh -c "sed -i "/^${key}=/c\\${key}=${val}" /www/.env"
fi
if [ $? -ne 0 ]; then
error "设置env参数失败!"
exit 1
fi
fi
}
# 初始化env
env_init() {
if [ ! -f ".env" ]; then
cp .env.docker .env
fi
if [ -z "$(env_get DB_ROOT_PASSWORD)" ]; then
env_set DB_ROOT_PASSWORD "$(rand_string 16)"
fi
if [ -z "$(env_get APP_ID)" ]; then
env_set APP_ID "$(rand_string 6)"
fi
if [ -z "$(env_get APP_IPPR)" ]; then
env_set APP_IPPR "10.$(rand 50 100).$(rand 100 200)"
fi
if [ -z "$(env_get UPDATE_TIME)" ]; then
env_set DB_HOST "mariadb"
env_set REDIS_HOST "redis"
docker run -it --rm -v ${WORK_DIR}:/www nginx:alpine sh -c "sed -i 's|/etc/nginx/conf.d/site/|/var/www/docker/nginx/site/|g' /www/docker/nginx/site/*.conf &> /dev/null"
fi
}
# 获取命令参数
arg_get() {
local find="n"
local value=""
for var in $INPUT_ARGS; do
if [[ "$find" == "y" ]]; then
if [[ ! $var =~ "--" ]]; then
value=$var
fi
break
fi
if [[ "--$1" == "$var" ]] || [[ "-$1" == "$var" ]]; then
find="y"
value="yes"
fi
done
echo $value
}
####################################################################################
####################################################################################
####################################################################################
# 显示帮助信息
show_help() {
cat << 'EOF'
DooTask 管理脚本
用法: ./cmd <命令> [参数]
📦 核心操作:
install 安装 DooTask (支持 --port <端口> --relock)
update 更新 DooTask (支持 --branch <分支> --force --local)
uninstall 卸载 DooTask
⚙️ 配置管理:
port <端口> 修改服务端口
url <地址> 修改访问地址
env <键> <值> 设置环境变量
debug [true|false] 切换调试模式
repassword [用户名] 重置数据库密码
🚀 开发构建:
serve, dev 启动开发模式
build, prod 生产环境构建
electron 构建桌面应用
🔧 服务管理:
up [服务名] 启动容器
down [服务名] 停止容器
restart [服务名] 重启容器
reup 重新构建并启动
💾 数据库操作:
mysql backup 备份数据库
mysql recovery 还原数据库
🛠️ 开发工具:
artisan <命令> 执行 Laravel Artisan 命令
composer <命令> 执行 Composer 命令
php <命令> 执行 PHP 命令
📚 其他:
doc 生成 API 文档
https 配置 HTTPS
--help, -h 显示此帮助信息
示例:
./cmd install --port 8080 安装并指定端口 8080
./cmd update --branch dev 切换到 dev 分支并更新
./cmd mysql backup 备份数据库
./cmd artisan migrate 执行数据库迁移
EOF
}
# 安装函数
handle_install() {
check_sudo
local relock=$(arg_get relock)
local port=$(arg_get port)
# 初始化文件
if [[ -n "$relock" ]]; then
rm -rf node_modules package-lock.json vendor composer.lock
fi
# 目录权限设置
volumes=(
"bootstrap/cache"
"docker"
"public"
"storage"
)
cmda=""
cmdb=""
for vol in "${volumes[@]}"; do
tmp_path="${WORK_DIR}/${vol}"
mkdir -p "${tmp_path}"
find "${tmp_path}" -type d -exec chmod 775 {} \;
rm -f "${tmp_path}/dootask.lock"
cmda="${cmda} -v ${tmp_path}:/usr/share/${vol}"
cmdb="${cmdb} touch /usr/share/${vol}/dootask.lock &&"
done
# 目录权限检测
remaining=10
while true; do
((remaining=$remaining-1))
writable="yes"
docker run --rm ${cmda} nginx:alpine sh -c "${cmdb} touch /usr/share/docker/dootask.lock" &> /dev/null
if [ $? -ne 0 ]; then
error "目录权限检测失败!请检查目录权限设置"
exit 1
fi
for vol in "${volumes[@]}"; do
if [ ! -f "${vol}/dootask.lock" ]; then
if [ $remaining -lt 0 ]; then
error "目录【${vol}】权限不足!"
exit 1
else
writable="no"
break
fi
fi
done
if [ "$writable" == "yes" ]; then
break
else
sleep 3
fi
done
# 设置端口
[[ "$port" -gt 0 ]] && env_set APP_PORT "$port"
# 启动PHP容器
$COMPOSE up php -d
# 安装PHP依赖
exec_judge "container_exec php 'composer install --optimize-autoloader'" "安装依赖失败"
# 最终检查
if [ ! -f "${WORK_DIR}/vendor/autoload.php" ]; then
error "安装依赖失败,请重试!"
exit 1
fi
# 生成应用密钥
[[ -z "$(env_get APP_KEY)" ]] && exec_judge "container_exec php 'php artisan key:generate'" "生成密钥失败"
# 设置生产模式
switch_debug "false"
# 数据库迁移
exec_judge "container_exec php 'php artisan migrate --seed'" "数据库迁移失败"
# 启动所有容器
$COMPOSE up -d --remove-orphans
success "安装完成"
echo -e "地址: http://${GreenBG}127.0.0.1:$(env_get APP_PORT)${Font}"
container_exec mariadb "sh /etc/mysql/repassword.sh"
}
# 更新函数
handle_update() {
check_sudo
local target_branch=$(arg_get branch)
local is_local=$(arg_get local)
local force_update=$(arg_get force)
# 检查是否已经安装
if [ ! -f "${WORK_DIR}/vendor/autoload.php" ]; then
error "请先执行安装命令"
exit 1
fi
# 尝试确定php容器启动
if [ -z "$(docker_name php)" ]; then
$COMPOSE start php
fi
if [[ -z "$is_local" ]]; then
# 检查本地修改
if ! git diff --quiet || ! git diff --cached --quiet; then
if [[ "$force_update" != "yes" ]]; then
warning "检测到本地修改,是否强制更新?[Y/n]"
read -r confirm_force
[[ -z ${confirm_force} ]] && confirm_force="Y"
case $confirm_force in
[yY][eE][sS] | [yY])
force_update="yes"
;;
*)
error "取消更新,请先处理本地修改"
exit 1
;;
esac
fi
fi
# 远程更新模式
exec_judge "git fetch --all" "获取远程更新失败"
# 确定目标分支
if [[ -n "$target_branch" ]]; then
current_branch="$target_branch"
if ! git config --get "branch.${current_branch}.remote" | grep -q "origin"; then
exec_judge "git config remote.origin.fetch '+refs/heads/*:refs/remotes/origin/*'" "设置远程Fetch配置失败"
fi
if ! git show-ref --verify --quiet refs/heads/${current_branch}; then
exec_judge "git fetch origin ${current_branch}:${current_branch}" "获取远程分支 ${current_branch} 失败"
fi
if [[ "$force_update" == "yes" ]]; then
exec_judge "git checkout -f ${current_branch}" "切换分支到 ${current_branch} 失败"
else
exec_judge "git checkout ${current_branch}" "切换分支到 ${current_branch} 失败"
fi
else
current_branch=$(git branch | sed -n -e 's/^\* \(.*\)/\1/p')
fi
# 检查数据库迁移变动
db_changes=$(git diff --name-only HEAD..origin/${current_branch} 2>/dev/null | grep -E "^database/" || true)
if [[ -n "$db_changes" ]]; then
echo "数据库有迁移变动,执行数据库备份..."
exec_judge "mysql_snapshot backup" "数据库备份失败" "数据库备份完成"
fi
# 更新代码
if [[ "$force_update" == "yes" ]]; then
exec_judge "git reset --hard origin/${current_branch}" "强制更新代码失败"
else
exec_judge "git pull --ff-only origin ${current_branch}" "代码拉取失败,可能存在冲突,请使用 --force 参数"
fi
# 更新依赖
exec_judge "container_exec php 'composer install --optimize-autoloader'" "更新PHP依赖失败"
else
# 本地更新模式
echo "执行数据库备份..."
exec_judge "mysql_snapshot backup" "数据库备份失败" "数据库备份完成"
fi
# 数据库迁移
exec_judge "container_exec php 'php artisan migrate'" "数据库迁移失败"
# 停止服务
$COMPOSE stop php nginx &> /dev/null
$COMPOSE rm -f php nginx &> /dev/null
# 启动服务
$COMPOSE up -d --remove-orphans
if [[ 0 -ne $? ]]; then
$COMPOSE down --remove-orphans
exec_judge "$COMPOSE up -d" "重启服务失败"
fi
env_set UPDATE_TIME "$(date +%s)"
success "更新完成"
}
# 卸载函数
handle_uninstall() {
check_sudo
# 确认卸载
echo -e "${RedBG}警告:此操作将永久删除以下内容:${Font}"
echo "- 数据库"
echo "- 应用程序"
echo "- 日志文件"
echo ""
read -rp "确认要继续卸载吗?(y/N): " confirm_uninstall
[[ -z ${confirm_uninstall} ]] && confirm_uninstall="N"
case $confirm_uninstall in
[yY][eE][sS] | [yY])
echo -e "${RedBG}开始卸载...${Font}"
;;
*)
echo -e "${GreenBG}终止卸载。${Font}"
exit 1
;;
esac
# 清理网络相关容器
remove_by_network
# 停止并删除容器
$COMPOSE down --remove-orphans
# 重置调试模式
env_set APP_DEBUG "false"
# 清理数据目录
find "./docker/mysql/data" -mindepth 1 -delete 2>/dev/null
find "./docker/logs/supervisor" -mindepth 1 -delete 2>/dev/null
find "./docker/appstore/config" -mindepth 1 -type d -exec rm -rf {} + 2>/dev/null
find "./docker/appstore/log" -name "*.log" -delete 2>/dev/null
find "./storage/logs" -name "*.log" -delete 2>/dev/null
success "卸载完成"
}
####################################################################################
####################################################################################
####################################################################################
# 优先处理帮助命令
if [[ "$1" == "help" ]] || [[ "$1" == "--help" ]] || [[ "$1" == "-h" ]] || [[ $# -eq 0 ]]; then
show_help
exit 0
fi
# 非electron命令需要检查Docker环境
if [[ "$1" != "electron" ]]; then
check_docker
env_init
fi
# 执行命令
case "$1" in
"install")
shift 1
handle_install
;;
"update")
shift 1
handle_update
;;
"uninstall")
shift 1
handle_uninstall
;;
"port")
shift 1
env_set APP_PORT "$1"
$COMPOSE up -d
success "修改成功"
echo -e "地址: http://${GreenBG}127.0.0.1:$(env_get APP_PORT)${Font}"
;;
"url")
shift 1
env_set APP_URL "$1"
restart_php
success "修改成功"
;;
"env")
shift 1
if [ -n "$1" ]; then
env_set $1 "$2"
fi
restart_php
success "修改成功"
;;
"repassword")
shift 1
container_exec mariadb "sh /etc/mysql/repassword.sh $@"
;;
"serve"|"dev")
shift 1
web_build dev
;;
"build"|"prod")
shift 1
web_build prod
;;
"appbuild"|"buildapp")
shift 1
electron_operate app "$@"
;;
"electron")
shift 1
electron_operate "$@"
;;
"eeui")
shift 1
cli="$@"
por=""
if [[ "$cli" == "build" ]]; then
cli="build --simple"
elif [[ "$cli" == "dev" ]]; then
por="-p 8880:8880"
fi
docker run -it --rm -v ${WORK_DIR}/resources/mobile:/work -w /work ${por} kuaifan/eeui-cli:0.0.1 eeui ${cli}
;;
"npm")
shift 1
npm "$@"
pushd electron || exit
npm "$@"
popd || exit
docker run --rm -it -v ${WORK_DIR}/resources/mobile:/work -w /work --entrypoint=/bin/bash node:16 -c "npm $@"
;;
"doc")
shift 1
container_exec php "php app/Http/Controllers/Api/apidoc.php"
docker run -it --rm -v ${WORK_DIR}:/home/node/apidoc kuaifan/apidoc -i app/Http/Controllers/Api -o public/docs
container_exec php "php app/Http/Controllers/Api/apidoc.php restore"
;;
"debug")
shift 1
switch_debug "$@"
echo "success"
;;
"https")
shift 1
if [[ "$1" == "agent" ]] || [[ "$1" == "true" ]]; then
env_set APP_SCHEME "true"
elif [[ "$1" == "close" ]] || [[ "$1" == "auto" ]]; then
env_set APP_SCHEME "auto"
else
https_auto
fi
restart_php
;;
"artisan")
shift 1
e="php artisan $@" && container_exec php "$e"
;;
"php")
shift 1
if [[ "$1" == "restart" ]] || [[ "$1" == "reboot" ]]; then
restart_php
else
e="php $@" && container_exec php "$e"
fi
;;
"nginx")
shift 1
e="nginx $@" && container_exec nginx "$e"
;;
"redis")
shift 1
e="redis $@" && container_exec redis "$e"
;;
"mysql")
shift 1
if [[ "$1" == "backup" ]] || [[ "$1" == "b" ]]; then
mysql_snapshot backup
elif [[ "$1" == "recovery" ]] || [[ "$1" == "r" ]]; then
mysql_snapshot recovery
else
e="mysql $@" && container_exec mariadb "$e"
fi
;;
"composer")
shift 1
e="composer $@" && container_exec php "$e"
;;
"service")
shift 1
e="service $@" && container_exec php "$e"
;;
"super"|"supervisorctl")
shift 1
e="supervisorctl $@" && container_exec php "$e"
;;
"models")
shift 1
container_exec php "php app/Models/clearHelper.php"
container_exec php "php artisan ide-helper:models -W"
;;
"translate")
shift 1
container_exec php "cd /var/www/language && php translate.php"
;;
"restart")
shift 1
$COMPOSE stop "$@"
$COMPOSE start "$@"
;;
"reup")
shift 1
remove_by_network
$COMPOSE down --remove-orphans
$COMPOSE up -d
;;
"down")
shift 1
remove_by_network
if [[ $# -eq 0 ]]; then
$COMPOSE down --remove-orphans
else
$COMPOSE down "$@"
fi
;;
"up")
shift 1
if [[ $# -eq 0 ]]; then
$COMPOSE up -d --remove-orphans
else
$COMPOSE up "$@"
fi
;;
*)
$COMPOSE "$@"
;;
esac