linux为常用压缩解压命令创建别名
1 | # .tar.gz / .tgz |
统一了不同格式的压缩解压命令,省略了参数,只支持最常用的情况,即:
· 压缩当前路径下的指定目录形成同名的压缩文件
· 提取当前路径下的指定压缩文件的内容到当前路径
压缩用法,压缩当前路径下的 foo 目录
1 | tgzc foo |
1 | tgzc foo/ |
1 | tgzc ./foo |
都可以在当前目录生成 foo.tar.gz
解压用法,解压当前路径下的 foo.7z 文件到当前路径下
1 | 7zx foo.7z |
1 | # .tar.gz / .tgz |
统一了不同格式的压缩解压命令,省略了参数,只支持最常用的情况,即:
· 压缩当前路径下的指定目录形成同名的压缩文件
· 提取当前路径下的指定压缩文件的内容到当前路径
压缩用法,压缩当前路径下的 foo 目录
1 | tgzc foo |
1 | tgzc foo/ |
1 | tgzc ./foo |
都可以在当前目录生成 foo.tar.gz
解压用法,解压当前路径下的 foo.7z 文件到当前路径下
1 | 7zx foo.7z |
添加源,默认的稳定源里最新只有gcc8,如果需要更高的版本需要添加这个测试源,这一步不是必须做,可以先看看默认的源里是否已经有了你想要的版本
1 | sudo add-apt-repository ppa:ubuntu-toolchain-r/test |
更新软件列表
1 | sudo apt-get update |
安装想要升级的gcc/g++版本
1 | sudo apt-get install gcc-9 g++-9 |
查看目前存在的版本
1 | sudo updatedb && sudo ldconfig |
通过update-alternatives切换默认版本(本质是修改软连接,最后的数字是优先级,优先级高的自动为默认版本)
1 | sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-7 20 |
现在就升级好了,可以通过命令查看
1 | gcc --version |
BTW:
之后可以随时通过
1 | sudo update-alternatives --config gcc |
手动切换默认版本
而删除一个版本使用下面的命令
1 | sudo update-alternatives --remove gcc /usr/bin/gcc-9 |
安装scl源
1 | yum install -y centos-release-scl scl-utils-build |
查看可以安装的gcc版本
1 | yum list all --enablerepo='centos-sclo-rh' | grep gcc |
安装 devtoolset-9
1 | yum install -y devtoolset-9-gcc.x86_64 devtoolset-9-gcc-c++.x86_64 devtoolset-9-gcc-gdb-plugin.x86_64 |
开启一个指定gcc/g++版本的bash
1 | scl enable devtoolset-9 bash |
可以在/etc/profile 中加入,这样每次登录就自动切换到gcc-9的环境了
1 | # 安装基础的GCC环境和WGET,是后面通过源码编译安装高版本GCC的基础 |
1 | # 通过which确认当前使用的gcc和g++ |
执行cmake生成Makefile时,cmake会去发现系统上的gcc
我实际使用时,在centos上系统存在gcc时,通过
1 | scl enable devtoolset-9 bash |
切换gcc版本后,使用cmake生成Makefile会出现仍然使用系统默认gcc的情况
解决方式:切换gcc版本后指定CC和CXX环境变量指向需要使用的gcc和g++,再执行cmake
1 | export CC=`which gcc` |
/bin 存放基础命令的可执行文件和符号连接,包括cat, cp, ls, touch, rm等
/sbin 存放超级用户使用的基础的管理程序,包括ifup, iptables, mkfs, route, swapon等
/usr Unix Software Resource的缩写, 也就是系统软件资源所放置的目录,全部软件都安装在这里
/usr/bin 存放很多应用程序的可执行文件,包括akw, vim, gcc, go, cmake等
/usr/local/bin 存放安装出来的可执行文件,包括ipython, jupyter-notebook, pip, wheel等
/usr/sbin 存放一些非核心的管理程序和一些安装出来的daemon程序,包括useradd, nginx, netplan, mysqld, sshd等
/usr/include Linux下开发和编译应用程序需要的头文件
/usr/lib 动态链接共享库和静态档案库目录
/usr/src 源代码目录
/usr/doc 文档目录
/usr/man 帮助文档目录
/var variable的缩写,包含可变的数据文件
/var/log/ 各种程序的日志文件
/var/www/ nginx网站目录,相当于nginx的数据文件
/var/lib/ 各种程序运行时会改变的数据文件
/var/lib/docker/ docker的镜像和容器数据
/var/lib/mysql/ mysql数据库的数据
/var/lib/mongodb/ mongodb数据库的数据
/etc 包含所有系统管理和维护方面的配置文件
/etc/hosts 域名解析配置
/etc/resolv.conf 域名解析服务器配置
/etc/init.d/ 自启动脚本,详见 配置Linux开机启动脚本(基于initd)
/etc/rc?.d/ 自启动脚本的软连接,?表示系统的运行级
/etc/profile 所有用户登录Shell时执行
/etc/profile.d/ 所有用户登录Shell时遍历目录下的脚本执行
/etc/issue Linux版本信息
/etc/sudoers 配置允许sudo的用户
/etc/passwd 用户列表 username:原密码占位符x:uid:gid:描述性信息:家目录:默认Shell
/etc/apt/sources.list apt软件源配置,详见 替换Ubuntu 18.04软件源
/etc/network/interfaces 网卡配置文件
/etc/netplan/*.yaml 网卡配置文件
/etc/fstab 系统启动时自动执行的挂载路径,也是mount -a时挂载的路径,详见 Linux NFS共享目录配置及开机自动挂载
/etc/exports 配置通过nfs共享的目录,详见 Linux NFS共享目录配置及开机自动挂载
/etc/samba/smb.conf 配置通过samba共享的目录
/etc/systemd/system/*.service 自启动的服务配置文件的符号连接,详见 配置Linux开机启动脚本(基于systemd)
/etc/docker/daemon.json docker配置文件
/etc/nginx/nginx.conf /etc/nginx/sites-enabled/default nginx配置文件,详见 nginx配置
/etc/mysql/my.cnf /etc/mysql/mysql.conf.d/mysqld.cnf mysql配置文件
/etc/redis/redis.conf redis配置文件
/lib 包含系统引导和在root用户执行命令时候所必需用到的共享库
/home 所有普通用户家目录的父目录
/root root用户的家目录
/opt 用户级的程序目录,自己下载解压的软件可以放在这个目录下,然后将可执行文件的符号连接创建到 /usr/local/bin
/boot 目录存放系统核心文件以及启动时必须读取的文件,包括Linux内核的二进制映像
/tmp 临时文件目录
/mnt 该目录是默认的文件系统临时装载点
/media 挂在多媒体设备的目录,如默认情况下软盘、光盘、U盘设备都挂在在此目录
/dev 目录保存着外部设备代码的文件,这些文件比较特殊,实际上它们都指向所代表的外围设备,如终端、磁盘驱动器、光驱、打印机等。
/proc 进程文件系统proc的根目录,其中的部分文件分别对应正在运行的进程,可用于访问当前进程的地址空间。它是一个非常特殊的虚拟文件系统,其中并不包含“实际的”文件,而是可用以引用当前运行系统的系统信息,如CPU、内存、运行时间、软件配置以及硬件配置的信息,这些信息是在内存中由系统自己产生的。
/sys 是一个类似于proc文件系统的特殊文件系统,用于将系统中的设备组织成层次结构,并向用户模式程序提供详细的内核数据结构信息。其实,就是在用户态可以通过对sys文件系统的访问,来看内核态的一些驱动或者设备等。
/run 目录中存放的是自系统启动以来描述系统信息的文件。比较常见的用途是daemon进程将自己的pid保存到这个目录。标准要求这个文件夹中的文件必须是在系统启动的时候清空,以便建立新的文件。
本文的操作在我的Ubuntu 18.04上并不能正常工作,我觉得这和系统启动是使用initd还是systemd有关
通过
1 | pstree -p|head -1 |
或
1 | ps -ef|awk '($2==1)' |
可以看到系统的1号进程,也就是启动全部进程的根进程是initd还是systemd。
systemd参考 配置Linux开机启动脚本(基于systemd)
先将脚本放在 /etc/init.d/ 下,例如脚本名为 new_service.sh
执行如下指令,在这里90表明一个优先级,越高表示执行的越晚
1 | cd /etc/init.d/ |
创建完成会在 /etc/rc*.d/ 下生成相应的软连接
rc后面的数字含义
软连接开头为Kxx或Sxx,Kxx表示不启动(似乎和这个文件不存在一样),Sxx表示启动,xx是启动顺序,01~99。
1 | sudo update-rc.d -f new_service.sh remove |
通过
1 | pstree -p|head -1 |
或
1 | ps -ef|awk '($2==1)' |
可以看到系统的1号进程,也就是启动全部进程的根进程是initd还是systemd。
initd参考 配置Linux开机启动脚本(基于initd)
基于systemd的自启动首先需要创建服务,在服务配置文件中配置调用需要自启动的脚本,然后设置服务自启动。
在 /lib/systemd/system/ 下新建.service文件,例如 kafka.service
1 | [Unit] |
其中最重要的,运行脚本,配置在ExecStart,如果脚本里面启动的程序是常驻内存的,这里不用设置后台运行。
After 用来配置服务的依赖项,表示服务器希望在哪些服务后启动。
WantedBy 类似系统的运行级别,如果只希望在图形界面自启动可以配置成 graphical.target ,默认配置成 multi-user.target 即可。
配置简单服务以上就够了,更详细的说明可以参考 Systemd 入门教程:实战篇 - 阮一峰的网络日志 (ruanyifeng.com)
修改服务配置文件后需要重新载入服务配置文件.
最后不要忘了设置服务自启动 systemctl enable kafka.service ,随便给出服务相关的常用命令。
都以kafka为例,清自行替换成其他服务。
1 | systemctl daemon-reload |
1 | systemctl enable kafka.service |
1 | systemctl is-enabled kafka.service |
1 | systemctl disable kafka.service |
1 | service kafka status |
1 | service kafka start |
1 | service kafka stop |
1 | service kafka status |
大学时候,尤其大二大三,因为参加ACM ICPC的关系,沉迷于在各大高校的OJ刷题(主要在 ZJU, PKU, HDU),回想起那时,写DP状态转移方程,编码,提交,AC一气呵成的爽快感至今仍然鲜活,以至于刚毕业那几年还时不时的做几道玩。
后来也许是工作忙了,也许是其他事情多了,也许是兴趣转移了(向投资),……,总之算来已经好久没有做题了。
今天从B站一个UP主那边发现了这个网站
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台 https://leetcode.cn
(从我的邀请连接注册学习可以帮我拿点积分)
似乎主要面向在职人群,我看还提供了面试求职之类的功能
新注册会询问你是在职还是学生,工作领域是前端、后端还是移动端等等。
然后就给我推了个新手专属题单
这我就忍不了了啊,水了一把

支持的语言有C++、Java、Python、JavaScript、Go、Rust等等,基本上传统主流和新兴主流语言都支持。
我发现答这种题我竟然还是倾向于用C++大于Python。
https://code.aliyun.com/daimingzhuang/flask-restful.git
1 | . |
python3
pip3 install -r requirements.txt
1 | flask |
根据项目情况配置 config.yml
修改 utils/db.py ,对数据模型(即数据库的表)进行定义。
在 resources 下新建资源,继承 BaseResource 中的某个基类,有需要时可重写get/post/put/delete方法实现自定义的业务逻辑。
在 resources/__init__.py 中添加资源的URI映射。
utils文件夹除了db.py,其他代码通用性都比较强,一般都只需使用无需修改。
resources文件夹除了BaseResource.py,其他代码可以认为都是示例,应该根据需要修改和删除。
httpsession存储在redis服务器中,前端的登录标识通过登录返回的header中的token字段和数据的{“data”: {“token”: “xxx”}}同时返回,前端后续的请求应该在header携带token字段(或token参数)以表明身份,具体可以看后面的请求示例。
开发环境
1 | python3 reset_server.py |
Linux上的生产环境
1 | gunicorn -b 0.0.0.0:8088 rest_server:app |
1 | GET http://localhost:8088/Token |
response text
1 | { |
1 | POST http://localhost:8088/Token |
response text
1 | { |
1 | GET http://localhost:8088/ |
response text
1 | "Hello, admin." |
1 | http://localhost:8088/Users?page=1&page_size=15&sort=username&order=asc&username_like=a%n |
response text
1 | { |
更多的查询条件使用方法,可以阅读 resources/BaseResource.py 中 ROPluralResource 类的 get 方法的源码
有时候和第三方对接,对方只提供了jar包接口,而我们的系统是Python实现的,这时候可以通过jpype库实现Python调用jar包里的代码。
为了完整说明,先写一个简单的Java类,然后打包成jar,再通过Python调用。
Hello.java
1 | class Hello |
编译得到Hello.class
1 | javac Hello.java |
创建jar包
1 | jar cf Hello.jar Hello.class |
安装jpype库
1 | pip3 install jpype1 |
调用示例
1 | # -*- coding: utf-8 -*- |
需要说明的是,一个进程只能启动一个JVM,并且JVM被关闭后不能再次启动,所以虽然jpype提供了关闭JVM的方法jpype.shutdownJVM(),我并没有封装在PyJar中,这样PyJar就可以视作对一个jar包的载入,在不同的.py文件里可以创建多个PyJar对象载入不同的jar包而不会出现JVM重复启动或者JVM已经终止的报错。
.java依赖jar包时的.class编译
1 | javac -classpath "/path1/1.jar:/path2/2.jar" abc.java |
在使用时需要通过addClassPath把依赖的包都加入进去。
如果.java文件中通过package com.xx.yy;指定了路径,那么打jar包时应该把当前目录cd到com的上层目录
1 | jar cf x.jar com/xx/yy/zz.class |
pom.xml 可以把很多java文件打在一个包中,我们可以自己编写或者我们得到了一个带有pom.xml的源码项目,可以使用如下命令打包.jar
1 | mvn clean package |
对于pom.xml依赖的jar包我们需要将其下载下来,通过命令
1 | mvn dependency:copy-dependencies |
这样我们就可以把打包出来的jar和依赖的jar一并提取出来拷到需要被python加载的路径下,通过上面类的addClassPath方法使用。
XXL-JOB是一个轻量级分布式任务调度框架。
它解决的问题是能在统一的界面上,方便的管理一堆定时执行的、或相互依赖的任务,让他们并行或以正确的顺序串行在一组机器上执行,并且对执行结果进行管理,包括执行日志,失败通知等。
https://www.xuxueli.com/xxl-job/
https://github.com/xuxueli/xxl-job
Maven3+
Jdk1.8+
Jre1.8+
Mysql5.7+
任务运行模式是指任务通过何种代码部署(粘合)到任务调度中心,默认的方式支持:Shell、Python、Nodejs、PowerShell等,比如我在下面添加了Python3
com.xxl.job.core.glue.GlueTypeEnum
1 | BEAN("BEAN", false, null, null), |
调度中心配置
1 | ./xxl-job-admin/src/main/resources/application.properties |
主要要确保数据库(xxl-job, datasource)配置正确
执行器配置
1 | ./xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/resources/application.properties |
主要注意两个地方:
调度中心地址
xxl.job.admin.addresses
执行器appname,相同appname的执行器构成一个执行器集群,在调度时不区分,不同的appname在配置任务时可选择由哪个appname的执行器执行
xxl.job.executor.appname
1 | ./doc/db/tables_xxl_job.sql |
重新构建
mvn clean package
增量构建
mvn package
构建完默认会生成
1 | ./xxl-job-admin/target/xxl-job-admin*.jar |
可以重命名并复制到其他路径,启动命令
1 | java -jar xxl-job-admin*.jar |
默认通过
1 | http://localhost:8080/xxl-job-admin/ |
访问调度中心,端口和路径在配置文件application.properties中可修改
用户名admin,密码123456,可以在登录后修改
构建完默认会生成
1 | ./xxl-job-executor-samples/xxl-job-executor-sample-springboot/target/xxl-job-executor*.jar |
可以重命名并复制到其他主机,启动命令
1 | java -jar xxl-job-executor*.jar |
启动后会根据配置自动向调度中心注册自己
1 | ldd <可执行文件名或so文件名> |
1 | ldd -r <可执行文件名或so文件名> |
-r 选项除了输出依赖的动态库(缺失会输出 not found)还会输出缺失的符号(undefined symbol)
1 | cat /proc/<PID>/maps|awk '{print $6}'|grep '\.so'|sort|uniq |
1 | lsof -p <PID>|awk '{print $NF}'|grep '\.so'|sort|uniq |
1 | pmap -p <PID>|awk '{print $4}'|grep '\.so'|sort|uniq |
3个命令输出结果应该是一样的
当存在不同版本so的时候可以用来确保使用到的是正确路径下的版本