linux
shell变量含义
- $# 是传给脚本的参数个数
- $0 是脚本本身的名字
- $1 是传递给该shell脚本的第一个参数
- $2 是传递给该shell脚本的第二个参数
- $3 是传递给该shell脚本的第三个参数
- $@ 是传给脚本的所有参数的列表
- $* 是以一个单字符串显示所有向脚本传递的参数,与位置变量不同,参数可超过9个
- $$ 是脚本运行的当前进程ID号
- $? 是显示最后命令的退出状态,0表示没有错误,其他表示有错误
es修复分片
通过explain api
查看详细情况
[root@sh ~]# curl -s -XGET localhost:9200/_cluster/allocation/explain?pretty
{
"index" : "index-net-20210902-3",
"shard" : 3,
"primary" : true,
"current_state" : "unassigned",
"unassigned_info" : {
"reason" : "ALLOCATION_FAILED",
"at" : "2021-09-28T03:10:58.099Z",
"failed_allocation_attempts" : 5,
"details" : """failed shard on node [LwWiAwmdQCiEibtiF7oqxQ]: failed recovery, failure RecoveryFailedException[[device_search_20201204][3]: Recovery failed on {reading_9.10.126.164_node2}{LwWiAwmdQCiEibtiF7oqxQ}{YVadGK2FSDKbR69l0Wu0xg}{9.10.126.164}{9.10.126.164:9300}{dil}{ml.machine_memory=539647844352, xpack.installed=true, ml.max_open_jobs=20}]; nested: IndexShardRecoveryException[failed recovery]; nested: ElasticsearchException[java.io.IOException: failed to read /data1/containers/1612339152002810932/es/data/nodes/0/indices/b0Ar9gFpQc6_oHhrdHYxGQ/7/_state/retention-leases-1518.st]; nested: IOException[failed to read /data1/containers/1612339152002810932/es/data/nodes/0/indices/b0Ar9gFpQc6_oHhrdHYxGQ/7/_state/retention-leases-1518.st]; nested: IOException[org.apache.lucene.index.CorruptIndexException: codec footer mismatch (file truncated?): actual footer=892219961 vs expected footer=-1071082520 (resource=BufferedChecksumIndexInput(SimpleFSIndexInput(path="/data1/containers/1612339152002810932/es/data/nodes/0/indices/b0Ar9gFpQc6_oHhrdHYxGQ/7/_state/retention-leases-1518.st")))]; nested: CorruptIndexException[codec footer mismatch (file truncated?): actual footer=892219961 vs expected footer=-1071082520 (resource=BufferedChecksumIndexInput(SimpleFSIndexInput(path="/data1/containers/1612339152002810932/es/data/nodes/0/indices/b0Ar9gFpQc6_oHhrdHYxGQ/7/_state/retention-leases-1518.st")))]; """,
"last_allocation_status" : "no"
}
}
方案一:修复分片
retention-leases-1518.st 这个文件的损坏,与这个文件曾经有一段时间不在线有关系。也就是说,与机器重启有关。如果要恢复的话,则需要手动删除这个文件,然后重新尝试分配分片:
[root@sh ~]# curl -s -XPOST localhost:9200/_cluster/reroute?retry_failed=true
{
"acknowledged": true,
"state": {
"cluster_uuid": "LOk2L8k5RsmCC7eg2y3h8A",
"version": 533752,
"state_uuid": "jVm_8aAIT6ug9NBJazjVig",
"master_node": "kHbBiclxR5-c-rsra2A5Jg",
"blocks": {
},
"nodes": {
"m5eloUNuTJak4xDRqf3FeA": {
"name": "1625799512002116132",
"ephemeral_id": "dqHmYahLSbuqvSkRXy2IPg",
"transport_address": "9.27.34.96:9300",
"attributes": {
"ml.machine_memory": "134587404288",
"rack": "cvm_33_330002",
"xpack.installed": "true",
"set": "330002",
"transform.node": "true",
"ip": "9.27.34.96",
"temperature": "hot",
"ml.max_open_jobs": "20",
"region": "33"
}
},
"security_tokens": {
}
}
}
方案二:分配陈腐的分片
如果删除损坏的.st文件无法使分片上线,则需要考虑使用reroute api分配stale primary。执行这个api之前,我们需要得到一些信息:
- 索引名称和分片ID可以通过
explain api
直观看到; - 节点名称可以通过
unassigned_info.details
得到。
根据这些信息,我们就可以执行reroute api了:
[root@sh ~]# curl -s -H "Content-Type:application/json" -XPOST "localhost:9200/_cluster/reroute?pretty" -d '
{
"commands": [
{
"allocate_stale_primary": {
"index": "{索引名称}",
"shard": "{分片ID}",
"node": "{节点名称}",
"accept_data_loss": true
}
}
]
}
方案三:丢弃分片
如果分配陈腐的分片也无法使分片上线,为了不影响索引读写请求,就只能丢弃掉损坏的分片了,这是最糟糕的情况:
[root@sh ~]# curl -s -H "Content-Type:application/json" -XPOST "localhost:9200/_cluster/reroute?pretty" -d '
{
"commands" : [
{
"allocate_empty_primary" : {
"index" : "{索引名称}",
"shard" : "{分片ID}",
"node" : "{节点名称}",
"accept_data_loss": true
}
}
]
}'
使用Lucene CheckIndex 修复
-exorcise
只能在紧急情况下使用,因为它将导致文件(也许是很多)被永久地从索引中删除。
- 在运行这个工具之前,一定要对你的索引做一个备份。
- 不要在一个正在被写入的索引上运行这个工具。
java -cp /usr/share/elasticsearch/lib/lucene-core-7.5.0.jar -ea:org.apache.lucene... org.apache.lucene.index.CheckIndex /work/elasticsearch/data/nodes/0/indices/uYrH-t7AR7e5mR2eCC7-6g/2/index -verbose -exorcise
结果返回 No problems were detected with this index.
话,说明索引没有损坏直接移除目录下的数据损坏标签 corrupted_*文件然后重启es
mv /work/elasticsearch/data/nodes/0/indices/uYrH-t7AR7e5mR2eCC7-6g/2/index/corrupted_H_wQlkOtQzKaz3dGkq_G-A /tmp
链接:
haproxy停用启用server
设置socket admin权限
stats socket /var/lib/haproxy/stats level admin
停用backend app下的server app1
echo "disable server app/app1" | socat stdio /var/lib/haproxy/stats
启用
echo "enable server app/app1" | socat stdio /var/lib/haproxy/stats
mysql导出文件
msyql5.7 secure_file_priv 用于限制数据导入导出操作:
- secure_file_priv 为 NULL 时,表示限制mysqld不允许导入或导出。
- secure_file_priv 为 /tmp 时,表示限制mysqld只能在/tmp目录中执行导入导出,其他目录不能执行。
- secure_file_priv 没有值 时,表示不限制mysqld在任意目录的导入导出。
因为 secure_file_priv
参数是只读参数,不能使用set global命令修改。需要在my.ini里加入 secure_file_priv=''
。
查看当前配置:
show global variables like '%secure_file_priv%';
导出csv:
select * from user into outfile '/tmp/user.csv' fields terminated by ',' optionally enclosed by '"' lines terminated by '\r\n';
导入数据:
load data local infile '/tmp/data.txt' replace into table mytable;
xtrabackup备份
yum install -y https://repo.percona.com/yum/percona-release-latest.noarch.rpm
yum install -y percona-xtrabackup-21.x86_64
备份:
创建备份用户
create user 'bakuser'@'localhost' identified by '123456';
grant reload, lock tables, process, replication client on *.* to 'bakuser'@'localhost';
flush privileges;
全量备份
xtrabackup -u bakuser -p 123456 --backup --target-dir=/data/dbbak/base
压缩备份
xtrabackup --backup --compress --compress-threads=4 --target-dir=/data/dbbak/base
备份指定数据库
xtrabackup -u bakuser -p 123456 --databases="db1 db2" --backup --target-dir=/data/dbbak/base
备份指定表
xtrabackup -u bakuser -p 123456 --databases="db1.tab1 db2.tab2" --backup --target-dir=/data/dbbak/base
恢复:
准备备份
#压缩过的需要先解压缩
xtrabackup --decompress --target-dir=/data/dbbak/base
xtrabackup --prepare --target-dir=/data/dbbak/base
恢复备份 --move-back 移动不保留备份 --copy-back 复制保留备份
#rsync -avrP /data/dbbak/base/ /var/lib/mysql/
xtrabackup --copy-back --target-dir=/data/dbbak/base
chown -R mysql:mysql /var/lib/mysql
增量备份:
创建全量备份
xtrabackup -u bakuser -p 123456 --backup --target-dir = /data/dbbak/base
创建增量备份 inc1
xtrabackup -u bakuser -p 123456 --backup --target-dir=/data/dbbak/inc1 --incremental-basedir=/data/dbbak/base
创建增量备份 inc2
xtrabackup -u bakuser -p 123456 --backup --target-dir=/data/dbbak/inc2 --incremental-basedir=/data/dbbak/inc1
恢复增量备份:
准备备份
#压缩过的需要先解压缩
xtrabackup --decompress --target-dir=/data/dbbak/base
xtrabackup --prepare --apply-log-only --target-dir=/data/dbbak/base
xtrabackup --prepare --apply-log-only --target-dir=/data/dbbak/base --incremental-dir=/data/dbbak/inc1
xtrabackup --prepare --target-dir=/data/dbbak/base --incremental-dir=/data/dbbak/inc2
恢复备份
#rsync -avrP /data/dbbak/ /var/lib/mysql/
xtrabackup --copy-back --target-dir=/data/dbbak/
chown -R mysql:mysql /var/lib/mysql
恢复单个表:
yum install mysql-utilities -y
#从备份中读取表结构 复制创表语句在数据库创建表
mysqlfrm --diagnostic /data/dbbak/mydb/tb1.frm
#丢弃表空间
alter table tb1 discard tablespace;
#从备份中拷贝ibd文件
cp /data/dbbak/mydb/tb1.ibd /var/lib/mysql/mydb/
chown mysql. /var/lib/mysql/mydb/tb1.ibd
#载入表空间
alter table tb1 import tablespace;
链接:
- https://www.jianshu.com/p/19b986a39b5e
- https://www.percona.com/doc/percona-xtrabackup/2.4/index.html#advanced-features
- https://www.percona.com/doc/percona-xtrabackup/2.3/howtos/recipes_ibkx_stream.html
linux中文支持
centos
yum -y install fontconfig
#查看已安装的中文字体
fc-list :lang=zh
#安装中文字体
yum install wqy-zenhei-fonts wqy-microhei-fonts
#刷新字体缓存
fc-cache -f -v
debian
#查看当前环境语言
locale
#安装中文字体
apt-get install xfonts-wqy ttf-wqy-zenhei ttf-wqy-microhei
#添加中文环境支持
dpkg-reconfigure locales
#通过空格选择 选择后确认添加
#zh_CN,UTF-8 UTF-8
ubuntu
# 安装中文字体
apt install fonts-wqy-microhei ttf-wqy-zenhei
#生成中文环境
sudo locale-gen zh_CN.UTF-8
#输入法
#安装输入法
sudo apt install fcitx fcitx-googlepinyin
#生成dbus机器码
dbus-uuidgen > /var/lib/dbus/machine-id
#配置环境变量,/etc/profile.d/fcitx.sh
#!/bin/bash
export QT_IM_MODULE=fcitx
export GTK_IM_MODULE=fcitx
export XMODIFIERS=@im=fcitx
export DefaultIMModule=fcitx
fcitx-autostart &>/dev/null
#配置 Fcitx 的输入法选项
fcitx-config-gtk3
#运行fcitx
fcitx-autostart
logrotate日志切割
logrotate 是基于 cron 每天运行
配置文件示例:
/var/log/zabbix/zabbix_agentd.log {
weekly
rotate 12
compress
delaycompress
missingok
notifempty
create 0664 zabbix zabbix
}
/var/log/cron
/var/log/maillog
/var/log/messages
/var/log/secure
/var/log/spooler
{
missingok
sharedscripts
postrotate
/bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true
endscript
}
/var/log/httpd/*log {
missingok
notifempty
sharedscripts
delaycompress
postrotate
/bin/systemctl reload httpd.service > /dev/null 2>/dev/null || true
endscript
}
/var/log/tinyproxy/tinyproxy.log {
daily
rotate 10
missingok
notifempty
compress
sharedscripts
postrotate
[ ! -f /var/run/tinyproxy/tinyproxy.pid ] || kill -HUP `cat /var/run/tinyproxy/tinyproxy.pid`
endscript
}
- monthly: 日志文件将按月轮循。其它可用值为 daily,weekly 或者 yearly。
- rotate 5: 一次将存储 5 个归档日志。对于第六个归档,时间最久的归档将被删除。
- compress: 在轮循任务完成后,已轮循的归档将使用 gzip 进行压缩。
- delaycompress: 总是与 compress 选项一起用,delaycompress 选项指示 logrotate 不要将最近的归档压缩,压缩 将在下一次轮循周期进行。这在你或任何软件仍然需要读取最新归档时很有用。
- missingok: 在日志轮循期间,任何错误将被忽略,例如 “文件无法找到” 之类的错误。
- notifempty: 如果日志文件为空,轮循不会进行。
- create 644 root root: 以指定的权限创建全新的日志文件,同时 logrotate 也会重命名原始日志文件。
- postrotate/endscript: 在所有其它指令完成后,postrotate 和 endscript 里面指定的命令将被执行。在这种情况下,rsyslogd 进程将立即再次读取其配置并继续运行。
常用配置参数:
- daily :指定转储周期为每天
- weekly :指定转储周期为每周
- monthly :指定转储周期为每月
- rotate count :指定日志文件删除之前转储的次数,0 指没有备份,5 指保留 5 个备份
- tabooext [+] list:让 logrotate 不转储指定扩展名的文件,缺省的扩展名是:.rpm-orig, .rpmsave, v, 和~
- missingok:在日志轮循期间,任何错误将被忽略,例如 “文件无法找到” 之类的错误。
- size size:当日志文件到达指定的大小时才转储,bytes (缺省) 及 KB (sizek) 或 MB (sizem)
- compress: 通过 gzip 压缩转储以后的日志
- nocompress: 不压缩
- copytruncate:用于还在打开中的日志文件,把当前日志备份并截断
- nocopytruncate: 备份日志文件但是不截断
- create mode owner group : 转储文件,使用指定的文件模式创建新的日志文件
- nocreate: 不建 立新的日志文件
- delaycompress: 和 compress 一起使用时,转储的日志文件到下一次转储时才压缩
- nodelaycompress: 覆盖 delaycompress 选项,转储同时压缩
- errors address : 专储时的错误信息发送到指定的 Email 地址
- ifempty :即使是空文件也转储,这个是 logrotate 的缺省选项
- notifempty :如果是空文件的话,不转储
- mail address : 把转储的日志文件发送到指定的 E-mail 地址
- nomail : 转储时不发送日志文件
- olddir directory:储后的日志文件放入指定的目录,必须和当前日志文件在同一个文件系统
- noolddir: 转储后的日志文件和当前日志文件放在同一个目录下
- prerotate/endscript: 在转储以前需要执行的命令可以放入这个对,这两个关键字必须单独成行
pm2
fork模式:单实例多进程不支持端口复用。支持配置interpreter使用pm2运行js之外的语言,例如php、python等等。
cluster模式:多实例多进程,只支持node,端口可以复用,实现负载均衡、共享TCP连接。
npm install -g pm2
常用命令:
-
npm启动
pm2 start npm --name "myapp" -- start
-
npm启动指定脚本
pm2 start npm --name "myapp" -- run "start:dev"
-
指定参数启动
pm2 start app.js --node-args="--max-old-space-size=1024"
-
启动app.js应用程序
pm2 start app.js
-
启动4个app.js的应用实例cluster模式
pm2 start app.js -i 4
-
启动应用程序并命名为myapp
pm2 start app.js --name="myapp"
-
当文件变化时自动重启应用
pm2 start app.js --watch
-
通过config文件启动
pm2 start ecosystem.config.js
-
列出 PM2 启动的所有的应用程序
pm2 list
-
显示每个应用程序的CPU和内存占用情况
pm2 monit
-
显示应用程序的所有信息
pm2 show [app-name]
-
显示所有应用程序的日志
pm2 logs
-
显示指定应用程序的日志
pm2 logs [app-name]
-
清空所有日志
pm2 flush
-
停止所有的应用程序
pm2 stop all
-
停止 id为 0的指定应用程序
pm2 stop 0
-
重启所有应用
pm2 restart all
-
重新加载所有应用
pm2 reload all
-
关闭并删除所有应用
pm2 delete all
-
删除指定应用 id 0
pm2 delete 0
-
把应用扩展到10个实例
pm2 scale [app-name] 10
-
增加2个实例
pm2 scale [app-name] +2
-
重置重启次数
pm2 reset [app-name]
-
创建开机自启动命令
pm2 startup
-
保存当前应用列表
pm2 save
-
更新pm2 ,保存进程>杀死PM2>恢复进程
pm2 update
-
生成ecosystem.config.js模板
pm2 init
pm2 init simple
pm2 ecosystem
module.exports = {
apps : [{
name: 'myapp', // 项目名
script: 'index.js', // 执行文件
cwd: './', // 工作目录
args: '', // 传递给脚本的参数
interpreter: '/usr/bin/python', // 指定的脚本解释器,默认node
interpreter_args: '', // 传递给解释器的参数
watch: '.', // 是否监听文件变动然后重启
ignore_watch: [ // 不用监听的文件或目录
'node_modules,
'logs'
],
exec_mode: 'fork', // 启动应用程序的模式,可以是cluster或fork,默认fork。
instances: 4, // 应用启动实例个数
max_memory_restart: '8G', // 最大内存限制数,超出自动重启
error_file: './logs/app-err.log', // 错误日志文件
out_file: './logs/app-out.log', // 正常日志文件
merge_logs: true, // 设置追加日志而不是新建日志
log_date_format: 'YYYY-MM-DD HH:mm:ss', // 指定日志文件的时间格式
min_uptime: '60s', // 应用运行少于时间被认为是异常启动
max_restarts: 30, // 最大异常重启次数,即小于min_uptime运行时间重启次数;
autorestart: true, // 默认为true, 发生异常的情况下自动重启
cron_restart: '1 0 * * *', // crontab时间格式重启应用;
restart_delay: '60s' // 异常重启情况下,延时重启时间
env: { // 默认环境参数
PORT: 3003,
NODE_ENV: 'production',
MYNAME: 'aa'
},
env_dev: { // 自定义环境参数dev,当前指定为开发环境 pm2 start app.js --env dev
NODE_ENV: 'development',
MYNAME: 'bb'
},
env_test: { // 自定义环境参数test,当前指定为测试环境 pm2 start app.js --env test
NODE_ENV: 'test',
MYNAME: 'cc'
}
}, {
script: './service-worker/',
watch: ['./service-worker']
}],
deploy : {
production : {
user : 'SSH_USERNAME',
host : 'SSH_HOSTMACHINE',
ref : 'origin/master',
repo : 'GIT_REPOSITORY',
path : 'DESTINATION_PATH',
'pre-deploy-local': '',
'post-deploy' : 'npm install && pm2 reload ecosystem.config.js --env production',
'pre-setup': ''
}
}
};
windwos文件名到linux乱码
安装convmv:
yum -y install convmv
转换编码:
convmv --notest --nosmart -f gbk -t utf8 -r /data
参数:
- -f enc 源编码
- -t enc 新编码
- -r 递归处理子文件夹
- -i 交互文向转换
- --list 显示所有可用编码
- --nosmart 如果是utf8文件,忽略
- --notest 直接转换不测试
- --replace 文件相同直接替换
- --unescape 可以做一下转义,比如把%20变成空格
- --upper 全部转换成大写
redis
创建集群:
redis-cli --cluster create 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 127.0.0.1:7006 --cluster-replicas 1
添加节点:
-
添加master节点(master7008)
redis-cli --cluster add-node 127.0.0.1:7008 127.0.0.1:7000
-
添加slave节点(指定master-id的slave7009)
redis-cli --cluster add-node 127.0.0.1:7009 127.0.0.1:7000 --cluster-slave --cluster-master-id 46f0b68b3f605b3369d3843a89a2b4a164ed21e8
删除节点:
-
迁移哈希槽至别的节点
redis-cli --cluster reshard 127.0.0.1:7000 --cluster-from 46f0b68b3f605b3369d3843a89a2b4a164ed21e8 --cluster-to 2846540d8284538096f111a8ce7cf01c50199237 --cluster-slots 1024 --cluster-yes
-
删除master以及对应的slave节点
redis-cli --cluster del-node 127.0.0.1:7000 46f0b68b3f605b3369d3843a89a2b4a164ed21e8
导入数据:
-
数据从外部实例导入到 Redis 集群
redis-cli --cluster import 127.0.0.1:7001 --cluster-from 172.16.7.14:6379 --cluster-copy
-
数据从aof恢复数据到集群
redis-cli -c -p 7001 --pipe < appendonly.aof
修复槽:
[WARNING] Node 127.0.0.1:7003 has slots in migrating state 10867.
-
清除哈希槽中的任何导入/迁移状态
redis-cli -c -p 7001 cluster setslot 10867 stable
-
修复(槽对应的节点)
redis-cli --cluster fix 127.0.0.1:7003
迁移槽(from & to 对应节点id):
# cluster-slots 迁移槽的数量
redis-cli --cluster reshard 127.0.0.1:7001 --cluster-from 9a243bc1db6cd60689512b2c3c63e5962b2de0bb --cluster-to 3e96051497a2021c84d230831104f1f9e8c6430a --cluster-slots 5461 --cluster-yes
redis-cli下常用操作:
redis-cli -c -p 7001
-
指定或切换当前节点为node-id的slave(master时必须迁移走所有槽)
cluster replicate node-id
-
查看keyname对应的槽
cluster keyslot keyname