文章目录
python_2">一、安装python&使用虚拟环境
参见Arch Linux 定时运行python脚本(crontab)
python_4">二、python程序重要参数加密
2.1 非对称加密(RSA)
用某用户密钥加密后所得的信息,只能用该用户的解密密钥才能解密。如果知道了其中一个,并不能计算出另外一个。因此如果公开了一对密钥中的一个,并不会危害到另外一个的秘密性质。称公开的密钥为公钥;不公开的密钥为私钥。
参考“公钥加密”
- 生成RSA密钥对
- 私钥存储在服务器上(运维人员做好秘钥管理)
- 公钥公开给开发人员,用于代码中进行重要配置加密
2.2 生成密钥对
安装pycryptodome
pip install pycryptodome
python">from Crypto.PublicKey import RSAkey = RSA.generate(2048)
private_key = key.export_key()
with open("private.pem", "wb") as f:f.write(private_key)public_key = key.publickey().export_key()
with open("public.pem", "wb") as f:f.write(public_key)
2.4 以连接数据库参数加密为例
【RSA加密/解密】PKCS1_OAEP和PKCS1_v1_5
2.4.1 工具类RSA.py
python">from Crypto.Cipher import PKCS1_OAEP as PKCS1_cipher
from Crypto.PublicKey import RSA
# 读取密钥
def get_key(path):with open(path) as f:pem_data = f.read()return RSA.importKey(pem_data)
# 公钥加密
def encrypt(msg, pub_path):key = get_key(pub_path)cipher = PKCS1_cipher.new(key)encrypt_msg = cipher.encrypt(msg.encode("utf-8"))return base64.b64encode(encrypt_msg).decode()
# 私钥加密
def decrypt(msg, pri_path):key = get_key(pri_path)cipher = PKCS1_cipher.new(key)decrypt_data = cipher.decrypt(base64.b64decode(msg))return decrypt_data.decode("utf-8")if __name__ == '__main__':original_msg = "hello world"encrypted_data = encrypt(original_msg, "./pub_key.pem")print("encrypt_data:", encrypted_data)decrypted_data = decrypt(encrypted_data, "./pri_key.pem")print("decrypt_data:", decrypted_data)
三、一个简单的Flask项目
pip install Flask
my_first_flask.py
python">from flask import Flask, render_templateapp = Flask(__name__, template_folder="template")@app.route("/t/hello")
def hello_world():return "<p>Hello, World!</p>"
@app.route("/t/index")
def index():return render_template('index.html')
template/index.html
<h1>index</h1>
gunicorn_92">四、安装配置gunicorn
4.1 安装
Web项目开启异步workers
$ pip install gunicorn
# web 项目必须启用 Async Workers(使用eventlet)
$ pip install greenlet # Required for both
$ pip install eventlet # For eventlet workers
# web 项目必须启用 Async Workers(使用gevent)
$ pip install greenlet # Required for both
$ pip install gevent # For gevent workers
4.2 启动/配置(选择eventlet)
参考博客
配置说明-官网
4.2.1 命令行方式配置参数
# 运行
# -k 配置使用workers 默认sync(同步),异步根据不同安装选择eventlet/gevent
nohup python -m gunicorn -w 5 -k eventlet -b 0.0.0.0:9999 -t 120 my_first_flask:app >> my_first_flask.log 2>&1 &# 根据进程号优雅关闭
kill -TERM 13078
4.2.2 配置文件方式配置参数
gunicorn.conf.py
python">
# **运行配置**# 并行工作进程数
workers = 4# 指定每个工作者的线程数
threads = 2# 使用nginx反向代理,默认本地访问端口 9999
bind = '127.0.0.1:9999'## 修改是否重新加载
#reload = True#
#daemon = True## 超时时间,默认30
timeout=30worker_class='eventlet'# **日志文件配置**
#loglevel="info"
#accesslog="log/access.log"
#errorlog="log/error.log"
logconfig_dict = {'version':1,'disable_existing_loggers': True,"root": {"level": "INFO", "handlers": ["root_handler"]},'loggers':{"gunicorn.error": {"level": "INFO",# 打日志的等级可以换的,下面的同理"handlers": ["error_file"], # 对应下面的键"propagate": 1,"qualname": "gunicorn.error"},"gunicorn.access": {"level": "DEBUG","handlers": ["access_file"],"propagate": 0,"qualname": "gunicorn.access"}},'handlers':{"error_file": {"class": "logging.handlers.RotatingFileHandler","backupCount": 3,# "when":"D",# "interval":1,"maxBytes": 1024 * 1024 * 10,"formatter": "generic","encoding": "utf-8","filename": "log/gunicorn.error.log"},"access_file": {"class": "logging.handlers.TimedRotatingFileHandler","backupCount": 3,"when":"D","interval":1,"formatter": "generic","filename": "log/gunicorn.access.log",},"root_handler":{"class": "logging.handlers.TimedRotatingFileHandler","backupCount": 3,"when":"D","interval":1,"formatter": "generic","filename": "log/gunicorn.root.log",}},'formatters':{"generic": {"format": "'[%(process)d] [%(asctime)s] %(levelname)s [%(filename)s:%(lineno)s] %(message)s'", # 打日志的格式"datefmt": "[%Y-%m-%d %H:%M:%S %z]",# 时间显示方法"class": "logging.Formatter"},"access": {"format": "'[%(process)d] [%(asctime)s] %(levelname)s [%(filename)s:%(lineno)s] %(message)s'","class": "logging.Formatter"}}
}
# gunicorn当前的process id
pidfile="gunicorn.pid"
日志配置参照
五、安装配置nginx
5.1 安装
(1)使用包管理工具
# 安装
sudo pacman -S nginx# 验证是否安装成功
nginx -v
# 查看当前是否启动nginx(有master,worker)
ps -ef | grep nginx
# 查看当前nginx状态
systemctl status nginx
# 立即启动
systemctl start nginx
# 立即重启
systemctl restart nginx
# 设置开机自启动
(2)使用源码编译(TODO)
5.2 配置
/etc/nginx/nginx.conf
user http;
worker_processes auto;
worker_cpu_affinity auto;events {multi_accept on;worker_connections 1024;
}http {charset utf-8;sendfile on;tcp_nopush on;tcp_nodelay on;server_tokens off;log_not_found off;types_hash_max_size 4096;client_max_body_size 16M;log_format test 'upstat=$upstream_status';# MIMEinclude mime.types;default_type application/octet-stream;# loggingaccess_log /var/log/nginx/access.log;error_log /var/log/nginx/error.log warn;# load configsinclude /etc/nginx/conf.d/*.conf;include /etc/nginx/sites-enabled/*; server {listen 9888;server_name 172.XXX.XXX.XXX;location /test/ {proxy_pass http://localhost:9999/t/;}error_page 400 401 402 403 404 405 406 407 408 409 /40x.html;location = /40x.html {root /usr/share/nginx/html;}access_log /var/log/nginx/access_test.log test;}
}
假设本机ip地址为:172.XXX.XXX.XXX。
访问:172.XXX.XXX.XXX:9888/test/path1
,重定向到localhost:9999/t/path1
。
访问:172.XXX.XXX.XXX:9888/test/hello
,重定向到localhost:9999/t/hello
。
六、运维
gunicorn_290">6.1 启动gunicorn服务
文件名:start
#!/bin/bashif [ "$#" -lt 1 ]; thenecho "Please provide one argument."
elsesource ../bin/activatepython -m gunicorn --check-config $1 python -m gunicorn -c gunicorn.conf.py $1 -Ddeactivate
fi
[rebecca@study src]$. start my_first_flask:app
gunicorn_309">6.2 停止gunicorn服务
文件名:stop
#!/bin/bashhead -n 1 gunicorn.pid | xargs kill -TERM
[rebecca@study src]$. stop