django startup

安装

1
2
3
4
5
# 安装最新
$ pip3 install django

# 指定版本
$ pip3 install django==3.0.7

创建应用

1
2
3
4
5
# 创建Project
$ django-admin startproject mysite

# 创建应用
$ python3 manage.py startapp polls

配置

数据库

MySQL

使用 pymysql 库替代 mysqldb

1
2
3
4
5
6
7
8
# 安装
$ pip install pymysql

# 替换
## settings.py 中添加
import pymysql
pymysql.version_info = (1, 4, 13, 'final', 0)
pymysql.install_as_MySQLdb()

配置

1
2
3
4
5
6
7
8
9
10
11
12
# settings.py

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'test-db',
'HOST': '127.0.0.1',
'PORT': 3306,
'USER': 'root',
'PASSWORD': 'root'
}
}

python virtualenv

安装

1
2
3
4
5
6
7
8
# ubuntu
$ sudo apt install python3-pip # 安装pip3
## OR
$ sudo apt-get install python-pip python-dev python-virtualenv # for Python 2.7
$ sudo apt-get install python3-pip python3-dev python-virtualenv # for Python 3.n

# pip
$ pip3 install virtualenv

新建虚拟环境

1
2
3
4
5
6
$ virtualenv venv	# sample

$ virtualenv --no-site-packages venv # 不使用外部库; 默认不使用,在virtualenv>=20版本中移除,添加上可能会报错
$ virtualenv --system-site-packages venv # 使用系统库
$ virtualenv -p python3 venv # 指定Python版本
$ virtualenv --copies venv # 复制Python程序等,而不是链接

激活新环境

1
2
3
4
5
6
7
# 进入环境
$ cd venv
# 激活
$ source bin/activate

$ source bin/activate # bash, sh, ksh, or zsh
$ source bin/activate.csh # csh or tcsh

退出环境

1
deactivate

配合supervisor

supervisor配置文件

1
2
3
4
5
6
7
8
9
10
11
[program:myproj-uwsgi]
process_name=myproj-uwsgi
command=/home/myuser/.virtualenvs/myproj/bin/uwsgi
--chdir /home/myuser/projects/myproj
-w myproj:app
environment=PATH="/home/myuser/.virtualenvs/myproj/bin:%(ENV_PATH)s"
user=myuser
group=myuser
killasgroup=true
startsecs=5
stopwaitsecs=10

导出环境

1
2
3
4
# 导出
$ pip freeze > requirements
# 安装
$ pip install -r requirements

python requests

安装

1
$ pip3 install requests

引入

1
import requests

请求

1
2
headers = {'user-agent': '...'}
requests.get(url, headers=headers)

参数

1
2
3
4
5
6
7
8
# Get
payload = {'key1': 'value1', 'key2': ['value2', 'value3']}
r = requests.get(url, params=payload)

# Post Json
data = {'key': 'value'}
r = requests.post(url, data=json.dumps(data), headers=headers) # OR
r = requests.post(url, json=data)

读取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 返回码
r.status_code

# Json 数据
r.json()

# 读取二进制数据
r.content

# 读取图片
from PIL import Image
from io import BytesIO

i = Image.open(BytesIO(r.content))

# 保存到文件
with open(filename, 'wb') as fd:
for chunk in r.iter_content(chunk_size=128):
fd.write(chunk)

树莓派配置

Wifi认证及静态IP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#### Raspbian
$ cat /etc/network/interfaces
# ...
source-directory /etc/network/interfaces.d

auto wlan0
allow-hotplug wlan0
iface wlan0 inet static
address 192.168.8.160
netmask 255.255.255.0
network 192.168.8.1
gateway 192.168.8.1
broadcast 192.168.8.255
wpa-essid "..."
wpa-psk "..."

# wpa-essid: wifi名称
# wpa-psk: wifi 密码,psk认证

树莓派连接游戏手柄

驱动

xpadneo

依赖

1
2
# Raspbian
$ sudo apt install dkms raspberrypi-kernel-headers

安装

1
2
3
4
5
6
7
8
9
$ git clone https://github.com/atar-axis/xpadneo.git
$ cd xpadneo
$ sudo ./install.sh

# 如遇如下报错
# Your kernel headers for kernel 4.19.97-v7l+ cannot be found at
# /lib/modules/4.19.97-v7l+/build or /lib/modules/4.19.97-v7l+/source.
# 将 /lib/modules 下拷贝一份至缺失版本,如:
# sudo cp -r /lib/modules/5.4.79-v7l+ /lib/modules/4.19.97-v7l+

连接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ bluetoothctl
$ [bluetooth]# scan on
...
# 长按xbox前侧配对键,至指示灯快速闪烁,出下如下新设备,记录其mac地址
[NEW] Device <MAC> Xbox Wireless Controller
...
[bluetooth]# pairable on
[bluetooth]# power on
[bluetooth]# pair <MAC>
[bluetooth]# trust <MAC>
[bluetooth]# connect <MAC>

# 如若报 Failed to connect: org.bluez.Error.Failed 错误,执行如下命令并重启系统
$ echo 'options bluetooth disable_ertm=Y' | sudo tee -a /etc/modprobe.d/bluetooth.conf

其他

1
2
# 查看设备
$ bluetoothctl devices

使用

Python

安装依赖

1
$ sudo pip3 install evdev asyncio

测试

1
2
3
4
5
6
$ cd xpadneo/misc/examples # 克隆下来的Git仓库
$ python3 python_asyncio_evdev/gamepad.py
press x to stop, Y to rumble light, B to rumble once, trigger and joystick right to see analog value
trigger_right = 32.98 joystick_right_x = 0

# 如果一切顺利,按手柄Y会感受到长震动;按B会感受到短震动;按X退出程序

按键

按键 code type 值类型
LT 10 03 区间,0~1023
RT 09 03 区间,0~1023
LB 310 01 单值,00,01
RB 311 01 单值,00,01
左摇杆 Y轴 01 03 区间,0~65535
左摇杆 X轴 00 03 区间,0~65535
右摇杆 Y轴 05 03 区间,0~65535
右摇杆 X轴 02 03 区间,0~65535
视图 158 01 单值,00,01
菜单 315 01 单值,00,01
十字键 上 17 03 单值,00,-1
十字键 下 17 03 单值,00,01
十字键 左 16 03 单值,00,-1
十字键 右 16 03 单值,00,01
Y 308 01 单值,00,01
X 307 01 单值,00,01
A 304 01 单值,00,01
B 305 01 单值,00,01

  • 摇杆X轴左侧为0,Y轴上侧为0

树莓派连接硬件

Speaker

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# play audio
$ sudo apt-get install sox libsox-fmt-all
$ play file-name.mp3

# turn volume
$ amixer set Master 50%
$ amixer set Master 10%+

# slelect speaker
$ alsamixer
## F6 to select device

# set volume over 100%
$ sudo apt install pulseaudio
$ pulseaudio --start -D
$ pulseaudio --check -v # check
$ sudo apt-get install pulseaudio-utils
$ pactl set-sink-volume 0 300%

Camera

Web Stream

1
2
# install
$ sudo apt-get install libjpeg8-dev imagemagick

Reference

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# setup and test
https://www.raspberrypi.org/documentation/configuration/camera.md

# official documents
https://www.raspberrypi.org/documentation/raspbian/applications/camera.md

# web stream
https://blog.miguelgrinberg.com/post/stream-video-from-the-raspberry-pi-camera-to-web-browsers-even-on-ios-and-android
https://blog.miguelgrinberg.com/post/how-to-build-and-run-mjpg-streamer-on-the-raspberry-pi
## 注释 mjpg-streamer/util.c stats.h
# // #include <linux/stat.h>
# // #include <sys/stat.h>

# generate stream
$ raspistill --nopreview -w 640 -h 480 -q 5 -o /home/pi/test.jpg -tl 100 -t 9999999 -th 0:0:0

# serve stream
$ LD_LIBRARY_PATH=/usr/local/lib mjpg_streamer -i "input_file.so -f /home/pi -n test.jpg" -o "output_http.so -w /usr/local/www"

# watch
http://rpi-ip:8080

L298N

参考

Linux之查看设备

CPU

1
$ lscpu

PCI 设备

1
$ lspci

块设备信息

1
2
3
4
5
6
7
$ lsblk

# 查看挂载的节点和对应的分区 UUID
$ ls -lha /dev/disk/by-uuid

# 查看块设备的信息,包含 UUID
$ blkid /dev/sda1

参数

  • -f 显示文件系统信息
  • -a 显示所有设备

硬盘

初始化步骤

  • 创建分区表
  • 创建分区
  • 格式化分区
  • 挂载分区
  • 配置启动时挂载

列出设备及分区信息

1
2
3
$ parted -l
#
$ fdisk -l

初始化设备

格式化

1
$ mkfs [options] [-t type fs-options] device [size]

示例

1
$ sudo mkfs -t ext4 /dev/sda

类型

  • ext4
  • FAT32
  • NTFS

使用中无法格式化

1
2
3
$ dmsetup status
$ dmsetup remove <>
$ dmsetup remove_all # 清楚所有, 谨慎使用, 最好挨个删除

创建主分区

打开存储盘

1
2
3
4
5
6
$ sudo parted -a optimal /dev/sda
GNU Parted 3.1
Using /dev/sda
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) select /dev/sdb # 切换至 /dev/sdb
Using /dev/sdb

创建分区表

1
(parted) mklabel [partition_table_type]

分区表类型

  • aix
  • amiga
  • bsd
  • dvh
  • gpt
  • mac
  • ms-dos
  • pc98
  • sun
  • loop

示例

1
(parted) mklabel gpt

检查

1
(parted) print

创建分区

1
2
3
4
5
6
7
# 主分区
(parted) print free
(parted) mkpart primary [start] [end] # 主分区模式

# lvm 分区
(parted) unit s
(parted) mkpart LVM ext4 0% 100%

示例

1
2
(parted) mkpart primary 0.00B 100GB   # 按容量 
(parted) mkpart primary 0 100% # 按比例

格式化分区

1
$ sudo mkfs.ext4 /dev/sda1

自动挂载分区

1
2
$ sudo mkdir data
$ sudo mount -t auto /dev/sda1 /data

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
$ sudo parted /dev/sda
GNU Parted 3.1
Using /dev/sda
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) print
Model: ATA Hitachi HUS72404 (scsi)
Disk /dev/sda: 4001GB
Sector size (logical/physical): 512B/4096B
Partition Table: loop
Disk Flags:

Number Start End Size File system Flags
1 0.00B 4001GB 4001GB ext4

(parted) mklabel gpt
Warning: The existing disk label on /dev/sda will be destroyed and all data on this disk will be lost. Do you want to continue?
Yes/No? yes
(parted) print
Model: ATA Hitachi HUS72404 (scsi)
Disk /dev/sda: 4001GB
Sector size (logical/physical): 512B/4096B
Partition Table: gpt
Disk Flags:

Number Start End Size File system Name Flags
(parted) mkpart primary 4096s 100% # 创建分区表
(parted) print
Model: ATA Hitachi HUS72404 (scsi)
Disk /dev/sda: 4001GB
Sector size (logical/physical): 512B/4096B
Partition Table: gpt
Disk Flags:

Number Start End Size File system Name Flags
1 2097kB 4001GB 4001GB primary
$ sudo mkfs.ext4 /dev/sda1
...
$ sudo mount -t auto /dev/sda1 /data
$ df -h
Filesystem Size Used Avail Use% Mounted on
devtmpfs 32G 0 32G 0% /dev
tmpfs 32G 0 32G 0% /dev/shm
tmpfs 32G 2.0G 30G 7% /run
tmpfs 32G 0 32G 0% /sys/fs/cgroup
/dev/mapper/centos-root 50G 4.2G 46G 9% /
/dev/nvme0n1p2 1014M 233M 782M 23% /boot
/dev/nvme0n1p1 200M 12M 189M 6% /boot/efi
/dev/mapper/centos-home 395G 332M 394G 1% /home
tmpfs 6.3G 12K 6.3G 1% /run/user/42
tmpfs 6.3G 0 6.3G 0% /run/user/1000
/dev/sda1 3.6T 89M 3.4T 1% /data

创建分区表时 4096s 的取值,可以参考 这里这里

脚本创建分区 & 格式化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 分区
parted --script /dev/vdb \
mklabel gpt \
mkpart primary 4096s 100%

# 格式化
mkfs.ext4 /dev/vdb1

# 挂载
mount -t auto /dev/vdb1 /data

# 写入 /etc/fstab, root 用户运行
echo -e "UUID=$(blkid -o value -s UUID /dev/sdb1)\t/data\text4\tdefaults\t0 0" >> /etc/fstab

echo -e "UUID=$(blkid -o value -s UUID /dev/sdb1)\t/downloads\text4\tdefaults\t0 0" >> /etc/fstab

创建 LVM 分区

概念

  • 物理卷(Physical Volumes)
  • 卷组(Volume Groups)
  • 逻辑卷(Logical Volumes)

查看信息

查看所有 LVM 可以管理的块设备

1
sudo lvmdiskscan

查看物理卷信息

1
2
3
4
5
6
7
8
9
sudo lvmdiskscan -l
#
sudo pvscan

# 如果需要展示更多信息
sudo pvs
#
sudo pvdisplay
sudo pvdisplay -m # 查看映射到每个卷的逻辑扩展名

查看 Volumn Group 的信息

1
sudo vgscan

查看 Logical Volumn 信息

1
2
3
sudo lvscan
#
sudo lvs

创建 LVM 卷

从 Raw Storage Device 创建 Physical Volumes

1
2
# 列出所有可用的设备
sudo lvmdiskscan

如果没有列出目标设备,可能是设备使用了不支持的分区表。重新设置设备的分区表为兼容的 BIOS 表。

1
2
3
sudo parted /dev/sda
(parted) mktable msdos
(parted) quit

标记存储设备为 LVM 物理卷。

1
2
3
sudo pvcreate /dev/sda
# 多个设备
sudo pvcreate /dev/sda /dev/sdb

从 Physical Volumes 创建 Volume Group

1
2
3
sudo vgcreate lvm-storage /dev/sda
# 多个设备
sudo vgcreate lvm-storage /dev/sda /dev/sdb

从 Volume Group 创建 Logical Volume

1
2
3
4
5
# 创建指定 size
sudo lvcreate -L 500G -n lvm-storage-hadoop lvm-storage

# 使用所有剩余空间
sudo lvcreate -l 100%FREE -n lvm-storage-hadoop lvm-storage

格式化分区

1
sudo mkfs.ext4 /dev/<lvm-vg-name>/<lvm-lv-name> 

挂载 LV

1
sudo mount /dev/<lvm-vg-name>/<lvm-lv-name> /path/to/destination

自动挂载

1
2
3
4
5
6
7
# 查看 logical volume 的 uuid
sudo blkid
/dev/mapper/<lvm-lv-name>: UUID="0192e4be-db57-4dc9-9f07-cb7bd673811b" BLOCK_SIZE="4096" TYPE="ext4"
# 添加自动挂载
sudo vim /etc/fstab
# 新增如下内容
UUID=0192e4be-db57-4dc9-9f07-cb7bd673811b /storage/hadoop ext4 defaults 0 2

更多操作

向 Volume Group 添加 Physical Volume

1
sudo vgextend <volume-group-name> /dev/sdb

增加 Logical Volume 的空间

Solution 1

1
2
3
4
sudo lvresize -L +5G --resizefs <lvm-vg-name>/<lvm-lv-name>  # 调整 lvm size
sudo lvresize -l +100%FREE /dev/<lvm-vg-name>/<lvm-lv-name> # 使用所有剩余空间
# sudo lvdisplay; 找到 Logical Volume 的 LV Path
sudo resize2fs <lv-path> # 生效

注意: lvresize 之后通过 df -h 查看空间,并不会生效,需要再运行 resize2fs

Solution 2

为 Ubuntu 的 lv 分区扩容

1
2
3
$ sudo vgdisplay  # 查看 vg 信息
$ sudo lvdisplay # 查看 lv 信息
$ sudo lvextend -l +100%FREE -r /dev/ubuntu-vg/ubuntu-lv

删除 Logical Volume

1
2
sudo umount /dev/<lvm-vg-name>/<lvm-lv-name>
sudo lvremove <lvm-vg-name>/<lvm-lv-name>

删除 Volume Group

1
2
sudo umount /dev/<lvm-vg-name>/* # unmount vg 下所有 lv
sudo vgremove <lvm-vg-name>

删除 Physical Volume

1
sudo pvremove /dev/sda

挂载新硬盘

1
2
3
4
5
6
7
8
9
10
11
# 创建文件系统
$ sudo mkfs -t ext4 /dev/sdb
# 分区
$ sudo parted -a optimal /dev/sdb
(parted) mklabel gpt
(parted) mkpart primary 0% 100%
# 格式化
$ sudo mkfs.ext4 /dev/vdb1
# 挂载
$ sudo mkdir /data
$ sudo mount -t auto /dev/sdb1 /data

查看接口

1
2
sudo dmidecode --type connector
# 可以查看 USB、SATA、M.2 接口

参考

Linux之网络配置

DNS

Debian+

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# interfaces; configured by dns-nameserver
$ cat /etc/network/interfaces
...
auto wlan0
allow-hotplug wlan0
iface wlan0 inet static
address 192.168.8.160
netmask 255.255.255.0
network 192.168.8.1
gateway 192.168.8.1
broadcast 192.168.8.255
wpa-essid "<wifi-id>"
wpa-psk "<wifi-password>"
dns-nameserver 8.8.8.8
dns-nameserver 8.8.4.4
dns-nameserver 192.168.8.1

Proxy

全局代理

1
2
export http_proxy=socks5://<host>:<port>
export https_proxy=socks5://<host>:<port>

适用

  • cURL

Git 代理

1
2
3
4
5
6
7
# 设置代理
git config --global https.proxy socks5://<host>:<port>
git config --global https.proxy socks5://<host>:<port>

# 取消
git config --global --unset http.proxy
git config --global --unset https.proxy

CMD ip

1
2
via : [FAMILY] ADDRESS, 指定下一跳地址
src : ADDRESS, 发送至目的地时优先使用的源地址

table

1
2
3
4
5
6
7
8
9
10
# show table
ip route show table all
ip route show table 10

# add table
ip route add 192.168.6.0/24 dev br0 table 10
ip route add default via 192.168.6.1 table 10

# 删除 table
ip route delete table 12 192.168.9.0/24

rule

1
2
3
4
5
# show rule
ip rule show

# 添加
ip rule add from 192.168.6.0/24 table 10 priority 1

gateway

1
2
3
4
5
# 添加
ip route add default via 192.168.1.1 dev eth0

# 更新 (所有配置都要添加vc)
ip route replace default via 192.168.1.1 dev eth0

静态路由

1
2
# github ip 走网关 192.168.6.68 
sudo ip route add 20.205.243.166 via 192.168.6.68

CMD route

1
2
# 添加路由
route -q -n add -inet 192.168.6.0/24 -interface utun3

Route Trace

1
2
3
$ traceroute -4 baidu.com
$ traceroute -6 baidu.com # ipv6
$ traceroute -g 192.168.6.1 # 指定 gateway

tcpdump

1
2
# 客户端抓取向服务端发送的数据
$ tcpdump dst host {dst-host} and dst port {dst-port} -w out.pacp