平时不怎么管理 SQL 数据库,一般就只知道 phpMyAdmin,服务商一般也只提供 phpMyAdmin。
现在在自己维护的服务器中安装一个 phpMyAdmin,真是吓到我了:.zip 下载下来有十几MB,解压完有 3000+ 个文件。然后我还不会配置,上网查教程搞了十分钟才连上。
后来找到了 Adminer,只有一个文件,传上去 1 分钟就能连上数据库。真是太适合只用来看一下数据库、稍微改点东西的用户了。推荐。
平时不怎么管理 SQL 数据库,一般就只知道 phpMyAdmin,服务商一般也只提供 phpMyAdmin。
现在在自己维护的服务器中安装一个 phpMyAdmin,真是吓到我了:.zip 下载下来有十几MB,解压完有 3000+ 个文件。然后我还不会配置,上网查教程搞了十分钟才连上。
后来找到了 Adminer,只有一个文件,传上去 1 分钟就能连上数据库。真是太适合只用来看一下数据库、稍微改点东西的用户了。推荐。
Docker 火了这么多年,我也要学习体验一下。就在阿里云的服务器上部署一个 Nginx+MariaDB+PHP 环境吧。
不同系统的安装方法见官方文档,包括了 Linux 的几个发行版和 Windows、MacOS 的详细步骤。我在 Linux 系统上安装。装完记得运行systemctl enable docker
把 docker 调成自动启动。
Docker 的各种 images 会发布在 Docker Hub,要善用这个网站来搜索想要的资源。
在创建 docker 容器(container)之前,先考虑一下网络的架构。我打算创建 3 个容器:nginx、mariadb、php,其中,需要暴露的端口只有 nginx 容器的 80 (443) 端口。根据这篇文档中的:
User-defined bridge networks are best when you need multiple containers to communicate on the same Docker host.
我应该选择 bridge 网络,bridge 的具体的使用见此文档。在宿主机上运行
docker network create --driver bridge my_bridge
创建一个名称为 my_bridge 的bridge。
先把 Nginx image 拉下来:docker pull nginx
,默认会拉 latest 这个 tag (tags 可以在 Docker Hub 先搜索 nginx 然后点进去找到)。
接下来创建容器:
docker run --name my_nginx --network my_bridge -p 80:80 -v /var/www/php_env:/usr/share/nginx/html -e TZ="Asia/Shanghai" -d --restart always nginx
参数解释:(详情见文档)
--name my_nginx 容器命名为my_nginx --network my_bridge 连接到my_bridge网络 -p 80:80 把容器的80端口(后)暴露为宿主机的80端口(前) -v /var/www/php_env:/usr/share/nginx/html 把宿主机的目录(前)mount到容器的指定路径 -e TZ="Asia/Shanghai" 设置环境变量 -d 在后台运行 --restart always 自动启动、重启 nginx image名称
如无意外,浏览器可以访问http://服务器IP
的网页了。
时不时就要百度一次这个问题,转载记录一下。
假如你正在 Windows 上写程序,又或者你正在和其他人合作,他们在 Windows 上编程,而你却在其他系统上,在这些情况下,你可能会遇到行尾 结束符问题。 这是因为 Windows 使用回车和换行两个字符来结束一行,而Mac和Linux只使用换行一个字符。 虽然这是小问题,但它会极大地扰乱跨平台协作。
Git 可以在你提交时自动地把行结束符 CRLF 转换成 LF,而在签出代码时把 LF 转换成 CRLF。用 core.autocrlf
来打开此项功能, 如果是在 Windows 系统上,把它设置成true
,这样当签出代码时,LF 会被转换成 CRLF:
$ git config --global core.autocrlf true
Linux 或 Mac 系统使用 LF 作为行结束符,因此你不想 Git 在签出文件时进行自动的转换;当一个以 CRLF 为行结束符的文件不小心被引入时你肯定想进行修正, 把 core.autocrlf
设置成 input 来告诉 Git 在提交时把 CRLF 转换成 LF,签出时不转换:
$ git config --global core.autocrlf input
这样会在 Windows 系统上的签出文件中保留 CRLF,会在 Linux 和 Mac 系统上,包括仓库中保留 LF。
如果你是 Windows 程序员,且别人也全在 Windows 上开发项目,可以设置false
取消此功能,把回车符记录在库中:
$ git config --global core.autocrlf false
转载自:http://www.qinbin.me/git-core-autocrlf%E9%85%8D%E7%BD%AE%E8%AF%B4%E6%98%8E/
记录一下我的部署过程。
文件为 /root/myproject/application.py
,其中的 Flask 实例为
app = Flask(__name__)
在 /root/myproject/
中新建一个虚拟环境 venv 并激活虚拟环境,使用 pip 安装 Flask 等模块。然后安装 gunicorn:
pip install gunicorn
装好之后,执行命令:
gunicorn --bind 127.0.0.1:8000 application:app # application为文件名 app为实例名
http://127.0.0.1:8000 应该是可以访问的。(服务器可能需要做一下端口转发,不然就绑定 0.0.0.0)
我希望服务器重启后,也可以自动启动 web server。
新建 /usr/lib/systemd/system/gunicorn.service,内容如下:
[Unit] Description=gunicorn daemon After=network.target [Service] WorkingDirectory=/root/myproject ExecStart=/root/myproject/venv/bin/gunicorn -w 1 --bind 127.0.0.1:8000 application:app PrivateTmp=true Environment=key=value [Install] WantedBy=multi-user.target
然后执行 systemctl enable gunicorn
,重启一下服务器,之后执行 systemctl status gunicorn
确认服务正常启动。这里备注一下“Environment=key=value”这一行,systemd 启动的服务是不带环境变量的,被这个坑了好久🤣。
最后,我使用 nginx 进行转发,和实现 https 访问。修改 /etc/nginx/conf.d/default.conf
server { listen 443 ssl; server_name myproject; access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; location / { proxy_pass http://127.0.0.1:8000; proxy_redirect off; proxy_set_header Host $host:$server_port; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } ssl_certificate /path/yourssl.cer; ssl_certificate_key /path/yourssl.key; ssl_session_timeout 5m; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; ssl_protocols TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; }
最后,测试一下 https://server_ip 看看能不能访问。
今年过年特别有空,来体验一下阿里云的轻量应用服务器。它境外的服务器,24元/月起,相比 ECS 和各种友商,是算便宜的(还是我没有找到更便宜的?)。体验好的话,本站也考虑搬过去。
先大概了解了一下,有人说它是基于 ECS 的 T5突发性能实例。我这里访问量不大,应该没问题。也有人说它可用性 <95%,这个就要自己试一下了。
购买的流程比 ECS 简单很多,最主要的是选择 “应用镜像”或“系统镜像”。应用镜像主要是一些网站了,WordPress、ECShop、phpwind等;系统镜像就和 ECS 的差不多,基本上就是系统,再给你自带阿里云的一些软件,云盾、监控什么的。整体流程 1 分钟可以走完。
阅读更多…大家都知道,Python 的运算性能不是很强,所以才有了那么多用 C/C++ 来计算的第三方 Python 包,还有各种各样的加速实践。
那么,应该加速哪些代码呢?我之前一般用自带的 cProfile,然而它的输出确实不是太好看,夹杂了非常多无用的信息。
最近才发现了 line_profiler 这个第三方扩展,用起来比 cProfile 直观很多。
pip install line-profiler
安装需要编译器。如果在 Windows 平台,需要自行先安装 C++ 编译器。如果不想装麻烦的 VC++,可以转而在 这里 下载别人编译好的 .whl 安装包。在 Linux/Mac 上面就简单很多,编译环境肯定有的。 最近发现新版的已经不需要了,Windows 也有了编译好的包,可以直接安装。
在需要 profile 的函数前,加上”@profile”,例如下面的 xxxxxx.py:
@profile def main(): l = [i for i in range(10000)] s = set(l) for _ in range(1000): if 9876 in l: pass if 9876 in s: pass if __name__ == '__main__': main()
这个”@profile”只是一个标记,不是 Python 的语句,所以会导致代码不能直接运行,只能用专门的方法运行(下面有),这不是太方便(目前的版本是这样)。
经过一点使用,了解到 @profile 的用法有一点限制,不可以对 class 打标签,但是可以打在 class 的方法上;子函数也可以用;并且可以同时 profile 多个函数 。
然后,运行:
kernprof -v -l xxxxxx.py
我们就得到了结果:
Wrote profile results to xxxxxx.py.lprof Timer unit: 1e-06 s Total time: 0.076552 s File: xxxxxx.py Function: main at line 2 Line # Hits Time Per Hit % Time Line Contents ============================================================== 2 @profile 3 def main(): 4 1 965.0 965.0 1.3 l = [i for i in range(10000)] 5 1 792.0 792.0 1.0 s = set(l) 6 7 1001 1278.0 1.3 1.7 for _ in range(1000): 8 1000 71133.0 71.1 92.9 if 9876 in l: 9 pass 10 1000 1297.0 1.3 1.7 if 9876 in s: 11 1000 1087.0 1.1 1.4 pass
可以发现,第 8 行的地方,无论是每次运行(Per Hit),还是总耗时(% Time),都占用了大量的时间。所以就改为第 10 行的用法,马上快了几十倍。
1. https://github.com/rkern/line_profiler
2. https://github.com/pyutils/line_profiler 这个是新版本
当前的项目需要对大型 numpy 数组进行各种运算(不是深度学习的那种运算),实践发现只开一个 python 进程时,只能使用一个 CPU 核心。所以考虑使用 multiprocessing 模块进行多进程运算。
但是,问题也很明显:用的是 multiprocessing.pool,如果我的 pool 的 size 是 4,一个 GB 级的 ndarray 传给 pool,会复制 4 份到每一个子进程。这首先会在传输时花时间做相应的 pickle 和 unpickle 操作;更重要的是,这坨数据会在内存里复制 4 份——这直接导致能处理的最大数据大小缩小了四分之三。
本文使用的 Python 版本为 3.6 / 3.7,Windows 系统。
在 3.8 版本中,新加入了 multiprocessing.shared_memory 模块,应该能简化这个问题。但是目前为止,项目使用的部分包还不支持 3.8,所以仍需要在旧版本中解决这个问题。
在 multiprocessing 包中,提供了一些可共享的对象:Value、Array、RawValue 与 RawArray。基本上,前者没有 Raw 的,可以加锁以进行进程间同步,后面 Raw 的没有锁。项目中用到的 numpy 数组都是只读的,子进程只需要读不需要写,所以选择使用 RawArray。
阅读更多…又是我一年一度的域名续费时间。我的 .com 域名在 Godaddy 已经快10年了,今年的续费又是没有优惠——$15 USD起。即使用上了“印度卢比大法”(把支付货币改为印度卢比),续费的价格也要 800 印度卢比,也就是大约 ¥80 人民币,或 $11 USD。
是不是 Godaddy 的广告打太多,导致其运营成本上升,羊毛出在羊身上?我专门找回了当年的订单记录,我在2014年续费的价格是 $9 USD,2011年甚至只用了 $7.xx。从2015年起,我的续费价格就没有低于 $10 了。
相比之下,Namesilo 只需要不到 $9 USD,想想还是转吧。下面是流程介绍。
阅读更多…