kubectl logs <pod> -n <namespace> --previous=true
All posts in 运维
环境:Centos7 + Jenkins + go1.16
问题1: mission $GOPATH
我在Jenkins中使用go的插件(可以自动下载特定版本),但是不知道为什么使用1.16版本是报mission $GOPATH
的错误,但是1.15不报,并且1.15也没有设置GOPATH。
经排查后发现这个服务器的jenkins用户环境变量中没有HOME这个环境变量。如果不配置GOPATH时,GOPATH默认为~/go
。
估计是1.16以后用户HOME查找目录,1.15及以前用其它方式查找。
为了不重启服务器,在jenkins的Configure System中增加了这个环境变量。
问题2: unrecognized relocation (0x2a) in section `.text’
在网上查这个错误说是Centos或ld版本太低导致,但是我用的Centos7版本不算太老。
按照网上的方法sudo yum -y install binutils
升级了ld后,问题解决
Mac中有个AppleScript,通过它可以实现弹窗或系统通知
弹窗
osascript -e 'display alert "告警!!" as critical'
- osascript -e 是执行一段apple script
- display alert是弹窗
- as critcal是用来控制图标,可以as三个值(informational,warning,critical,默认是informational)
发通知
osascript -e 'display notification "通知内容" with title "标题" subtitle "子标题" sound name "Glass"'
- display notification 是发通知的命令后面紧跟着通知内容
- with title 可以修改通知标题(默认是“脚本编辑器”)
- subtitle 可以添加一个子标题(默认没有)
- sound name 可以用来选择一种通知的声音,声音存放在
/System/Library/Sounds
中
结合PHP实战
<?php
ini_set('date.timezone','PRC');
$host = 'mysql.example.org';
$port = '3306';
$dbname = 'test';
$username = 'root';
$password = '123456';
$pdo = new PDO("mysql:host={$host};port={$port};dbname={$dbname};charset=UTF8", $username, $password);
$sql = <<<SQL
SELECT u.uid, p.privilege_id, u.updated_at
FROM user_privilege AS p
LEFT JOIN user AS u ON u.uid = p.uid
WHERE u.del = 1 and p.del = 0;
SQL;
$statement = $pdo->query($sql);
$result = $statement->fetchAll(PDO::FETCH_ASSOC);
$new = [];
$logDir = __DIR__ . '/log/';
if (!file_exists($logDir)) {
mkdir($logDir, 0755, true);
}
foreach ($result as $item) {
$fileName = $logDir . '/' . $item['uid'] . '.json';
if (!file_exists($fileName)) {
file_put_contents($fileName, json_encode($item, JSON_PRETTY_PRINT));
$new[] = $item['uid'];
}
}
if ($new) {
$msg = sprintf('%s发现新异常数据%d条!(%s)', date('Y-m-d H:i:s'), count($new), implode(', ', $new));
$cmd = <<<CMD
osascript -e 'tell application "System Events" to display alert "{$msg}" as critical'
CMD;
exec($cmd);
}
这个脚本连接一个远程的数据库,检查是否出现用户被删除,但是权限没有被删除的情况,如果发现将它记录到日志并弹窗提示。这里增加了tell application "System Events" to
这么个前缀,是指以“System Events”这个应用弹这个窗,这是因为好像有什么机制会阻止cron任务中直接弹窗,需要借用另一个应用的身份。也可以借用”Finder”,发弹窗时Finder会跳动一下,但是弹窗需要点Finder才能出来,而使用System Event可以直接弹出来。
接下来可以在执行crontab -e
来增加个计划任务
MAILTO=""
*/1 * * * * php ~/check.php > /dev/null
- MAILTO=”” 是执行crontab不发执行结果的系统邮件
- */1是指每1分钟执行一次,剩下的*分别代表:每小时(0~23)/每天(1~31)/每月(1~12)/每周几(0~6)
抓包发现jetpack发到网站的请求返回了faultCode:32700,jetpack parse error. not well formed的错误。
执行php -m查看发现没有安装xml扩展,apt install php7.2-xml解决
今天更新代码时出现了这个错误信息
error: cannot lock ref 'refs/remotes/origin/xxxx/log': 'refs/remotes/origin/xxxx' exists; cannot create 'refs/remotes/origin/xxxx/log'
From ssh://ssh.gitlab.oooo.com:22/MyGroup/composer
! [new branch] xxxx/log -> origin/xxxx/log (unable to update local ref)
出现这个问题的原因是,之前远程有一个xxxx分支,后来别人删掉远端了xxxx分支,又建了一个xxxx/log分支,但是本地还有xxxx的信息。这样就出现了git分支名冲突的问题,类似于文件系统中一个路径不可能既是文件又是目录。
这时需要执行这条命令:
git update-ref -d refs/remotes/origin/xxxx
单独更新一下本地的xxxx信息
最近发现服务器经常出现502的问题,但是并发量并没有达到那么高(fpm设置了500个进程)。看了一下nginx的配置
upstream fastcgi_backend {
server 127.0.0.1:9000;
server 127.0.0.2:9000;
server 127.0.0.3:9000;
server 127.0.0.4:9000;
}
4个IP的问题,问了运维,说是为了增加可以支撑连接数,但实际上这四个IP都是本地的fpm(我感觉这波优化没什么卵用)fpm总共500个,端口也能即时回收,所以应该也不是端口沾满的问题。
后来看日志,发现有一些timeout的请求,而且每一波502的请求附近都会有一些504,但是504也不算太多,不会将所有的fpm进程都占满。
看了nginx的文档后发现如果一个server无法处理响应了,会使用其它的server重试,并且多次无法处理响应(默认1次),nginx会临时将这个节点摘掉(默认10秒)。而fpm超时就被nginx认为是无法处理响应了,这时理论上会重试4次(相当于放大了问题)。
这就意味着如果10秒内有4个请求造成了fpm超时就会造成500个fpm进程都被认为是不可用。
优化程序是一种方案(正常来说不应该这么慢)。另外也可以优化一下nginx的配置
upstream fastcgi_backend {
server 127.0.0.1:9000 max_fails=0 fail_timeout=0;
}
鉴于我对4个IP的不认同,我将IP改回了一个。并且设置mx_fails=0即无论fpm是否可用都将请求转发至fpm,我觉得这样也没什么问题,如果fpm真的挂了,nginx应该也能处理。fail_timeout是一个无关紧要的参数,即如果服务挂了临时摘掉多少秒,因为mx_fails=0,所以这个参数设不设都可以。
最后/usr/local/openresty/nginx/sbin/nginx -t校验,/usr/local/openresty/nginx/sbin/nginx -s reload重新加载配置,问题解决。
约定
- /opt/start.sh :通用启动脚本,第一个参数指定应用名,如/opt/start.sh myapp
- /opt/stop.sh :通用停止脚本,第一个参数指定应用名,如/opt/stop.sh myapp
- /opt/<app_name>/<app_name>.jar :启动的应用jar包
- /opt/<app_name>/<app_name>.pid :启动后的进程id,由start.sh自动生成
- /opt/<app_name>/log/stdout.log :应用的标准输出,由start.sh自动生成
- /opt/<app_name>/log/stderr.log :应用的错误输出,由start.sh自动生成
- /opt/<app_name>.runuser :当以root运行start.sh时,应用的运行用户,如果没有这个文件将以root运行
启动脚本(start.sh)
#!/bin/bash
APP_NAME=$1
BASE_DIR=$(readlink -f $(dirname "$0"))
APP_DIR=${BASE_DIR}/${APP_NAME}
JAR_FILE=${APP_DIR}/${APP_NAME}.jar
PID_FILE=${APP_DIR}/${APP_NAME}.pid
LOG_DIR=${APP_DIR}/log
RUN_USER_FILE="${BASE_DIR}/${APP_NAME}.runuser"
RUN() {
if [ ${RUN_USER} ]; then
SCRIPT="$@"
return $(runuser -l ${RUN_USER} -c "${SCRIPT}" 2>/dev/null)
else
return $@
fi
}
if [ ! ${APP_NAME} ]; then
echo "App name not found!";
exit 1;
fi
if [ ! -f ${JAR_FILE} ]; then
echo "Jar file not found: ${JAR_FILE}";
exit 1;
fi
if [ -f ${PID_FILE} ]; then
echo "App is running!: $(cat ${PID_FILE})";
exit 1;
fi
RUN_USER=$(whoami)
if [ ${RUN_USER} == 'root' ]; then
if [ -f ${RUN_USER_FILE} ]; then
RUN_USER=$(cat ${RUN_USER_FILE});
fi
else
RUN_USER=''
fi
if [ ! -d ${LOG_DIR} ]; then
if ! RUN "mkdir ${LOG_DIR}"; then
echo "Start failed: can not create log directory.";
exit 1;
fi
fi
cd ${APP_DIR};
if ! RUN "nohup java -jar ${JAR_FILE} > ${LOG_DIR}/stdout.log 2>${LOG_DIR}/stderr.log & echo \$! > ${PID_FILE}" ; then
echo "Start failed: run failed!";
exit 1;
fi
echo "Started: ${JAR_FILE}";
停止脚本(stop.sh)
#!/bin/bash
APP_NAME=$1
BASE_DIR=$(dirname "$0")/${APP_NAME}
PID_FILE=${BASE_DIR}/${APP_NAME}.pid
if [ ! ${APP_NAME} ]; then
echo "App name not found!";
exit 1;
fi
if [ -f ${PID_FILE} ]; then
PID=$(cat ${PID_FILE});
echo kill ${PID}
kill ${PID};
rm -f ${PID_FILE};
else
echo "Not running...";
fi
exit 0;
最近买了几台云主机,写了个脚本初始化用户和权限
- 创建一个无密码的新用户
- 开启SSH登录
- 设为SUDOUser
- 禁用root用户
#!/bin/bash
NEWUSER='fyn'
IDRSA_PUB="*****"
useradd -m ${NEWUSER}
mkdir /home/${NEWUSER}/.ssh
echo ${IDRSA_PUB} > /home/${NEWUSER}/.ssh/authorized_keys
chown ${NEWUSER}:${NEWUSER} -R /home/${NEWUSER}
chmod 0600 /home/${NEWUSER}/.ssh/authorized_keys
echo -e "\n${NEWUSER} ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
chsh -s /bin/bash ${NEWUSER}
echo -e "\n127.0.0.1 $(hostname)" >> /etc/hosts
passwd -l root
nginx反向代理默认用的http1.0,如果尚有不支持http1.0,需要增加proxy_http_version 1.1
选项来指定版本
location /api {
proxy_http_version 1.1;
proxy_pass http://192.168.1.30:8080/;
}
netstat -ant|grep -v TIME_WAIT|awk -F '[[:space:]:]+' '{print $6"\t"$4":"$5}'|sort|uniq -c|sort -rg|grep :5672|head -n 20
netstat -ant
打印端口使用情况- a:全部
- n:显示端口号
- t: 只看tcp连接
|grep -v TIME_WAIT
去掉TIME_WAIT状态的连接(netstat中不加-n也可以)|awk -F '[[:space:]:]+' '{print $6"\t"$4":"$5}'
用空格和冒号拆分字符串,并重新拼接,只保留远程IP,本地IP和本地端口。- -F 设置分隔符
- {print $6} 打印第6个参数
|sort|uniq -c
先用sort排序然后通过uniq -c做分类汇总- -c将计数加入到第一列
|sort -rg
重新排序- -r:倒序排列
- -g:以数字的方式排序
|grep :5672
只找端口号为5672的|head -n 20
取前20条
netstat -ant|grep -v TIME_WAIT|awk '{match($4"\t"$5, /^([0-9\.]+:[0-9]+)\t([0-9\.]+):[0-9]+$/, a); if(a[1]) print a[2]"\t"a[1]}'|sort|uniq -c|sort -rg|grep 5672|head -n 20
- 通过match做精确匹配