You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flask应用Subprocess在systemd/cron启动时失效问题排查与解决

CTFd Webshell功能自动启动时Docker用户创建失败问题解决

问题场景

部署CTFd实例并开发Webshell功能,编写对应Flask页面代码实现自动为用户创建Docker容器内账户。通过flask run或手动执行gunicorn命令启动应用时,功能完全正常,Docker容器内用户账户可按预期创建,Webshell能正常使用。但配置自动启动(systemd服务或crontab)后,CTFd其他功能正常,唯独Webshell页面的subprocess调用无法工作,容器内账户无法创建。

Flask页面代码

from flask import render_template, session, redirect, url_for

from CTFd.models import db, Users, Teams
from CTFd.utils.decorators import admins_only, is_admin

from CTFd import utils

from uuid import uuid4 #used for random hex string generation
import subprocess #for executing commands to docker


container_name = "ctfd_wettytest_1" #CHANGE ME. Use whatever name you provided to your container
#useradd_cmd = F"docker exec -it {container_name} /usr/sbin/useradd -m -s /bin/bash -p $(openssl passwd -1 {password}) {username}"
return_info = "Pour acceder a votre instance Kali, cliquez <a href=http://192.168.192.134:8080/>ICI</a><br>Username: %s<br>Password: %s" #CHANGE ME. The URL needs to be yours.

login_info = {} #this stores login info. If CTFd webapp is restarted, the information is lost. New

def load(app):
    @app.route('/docker', methods=['GET'])
    def view_docker():
        #if utils.authed(): #make sure the user is logged in
            player = Users.query.filter_by(id=session['id']).first() #get user/team id.
            if player.id  in login_info: #if there is already login info for the user
                return_data =  return_info%(login_info[player.id][0],login_info[player.id][1])
                return render_template('page.html', content=return_data) #provide the login info to the user
            else: #if there is no login info for the user
                randomvalue = uuid4().hex[0:16] #generate random hex string
                username = randomvalue[:8]
                password = randomvalue[8:]
                login_info[player.id] = [username,password] #add login info into our dictionary
                useradd_cmd = F"/usr/bin/docker exec -it {container_name} /usr/sbin/useradd -m -s /bin/bash -p $(openssl passwd -1 {password}) {username}"
                subprocess.call(useradd_cmd, shell=True) #run a command to add a user to the container
                return_data = return_info%(login_info[player.id][0],login_info[player.id][1])
                return render_template('page.html', content=return_data) #provide the login info to the user
        #else: #if user isn't logged in, send them to the login page
            #return redirect(url_for('auth.login'))

手动启动gunicorn命令

gunicorn --bind unix:app.sock --keep-alive 2 --chdir /CTFd/ --workers 3 --worker-class gevent 'CTFd:create_app()' --access-logfile '/CTFd/CTFd/logs/access.log' --error-logfile '/CTFd/CTFd/logs/error.log' --bind 127.0.0.1:8000

systemd服务文件

[Unit]
Description=Gunicorn instance to serve ctfd
After=network.target

[Service]
User=ctfd
Group=docker
WorkingDirectory=/CTFd
Environment="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin"
ExecStart=gunicorn --bind unix:app.sock --keep-alive 2 --workers 3 --worker-class gevent 'CTFd:create_app()' --access-logfile '/CTFd/CTFd/logs/access.log' --error-logfile '/CTFd/CTFd/logs/error.log' --bind 127.0.0.1:8000


[Install]
WantedBy=multi-user.target

crontab自动启动配置

@reboot PATH=/usr/local/sbin:/usr/local/bin:/sur/sbin:/usr/bin gunicorn --bind unix:app.sock --chdir /CTFd --keep-alive 2 --workers 3 --worker-class gevent 'CTFd:create_app()' --access-logfile '/CTFd/CTFd/logs/access.log' --error-logfile '/CTFd/CTFd/logs/error.log' --bind 127.0.0.1:8000

排查过程

排查gunicorn的error.log未发现报错信息,进一步检查后定位到Docker报错:"The input device is not a TTY"。原因是systemd或crontab启动应用时,运行环境没有TTY终端,而Docker命令中使用了-it参数(该参数需要交互式TTY环境)。

解决方案

将Flask代码中useradd_cmd里的docker exec -it替换为docker exec -i,去掉强制分配TTY的t参数,修改后的命令如下:

useradd_cmd = F"/usr/bin/docker exec -i {container_name} /usr/sbin/useradd -m -s /bin/bash -p $(openssl passwd -1 {password}) {username}"

修改后重新部署,自动启动场景下Docker容器内的用户账户可正常创建,Webshell功能恢复正常。

内容的提问来源于stack exchange,提问作者Kptainflintt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 18:20:17