Nicksxs's Blog

What hurts more, the pain of hard work or the pain of regret?

在运行一个python写的小工具的时候碰到了这个问题
““Python.framework”已损坏,无法打开。 你应该将它移到废纸篓。”
一开始以为是常规问题,但是可能随着系统更新,也出现了比较不同的情况
首先进去”系统设置”->”隐私和安全性”
一开始是长这样的

发现没有任意来源了,
于是搜索了下,可以直接在当前环境下开启,这个是区别于之前的经验的,因为之前关闭 spctl 好像是需要进恢复模式的
我试了下在 mac os 14.3 中目前是可以直接把这个关闭掉

1
sudo spctl --master-disable

关闭后重新打开系统设置
就能看到任意来源了

捎带解释下这个 spctl 的意思是 System Policy Control
用于管理系统策略控制。 禁用Gatekeeper的主开关,允许运行任何来源的应用。
此命令会降低Mac的安全性,因为它允许运行未经验证的应用。 启用后,需小心下载和运行应用。
所以还是需要小心关闭,一般在确认来源可靠才能关闭

最近发现博客上那个阅读次数的功能有点问题,因为是基于leancloud的功能,然后前几天打开了下 leancloud.app 这个网站,发现打不开了,以为是不提供服务了,因为当时刚好没精力就没仔细去研究,后面点开具体一篇文章,提示说Counter未初始化,本身这个功能是基于 leancloud 实现的计数器,需要在博客构建的时候初始化本次新增文章的一个类似于键值对的计数对。
第一步思考的错误是网站搞错了,leancloud 的官网地址是 leancloud.cn,leancloud 的正确官网是可以打开的。
那么第二步的思考是可能换了接口或者调用方式,因为打开以后要求验证手机号码,以为是也加强了审核,需要通过手机绑定后才能继续访问,
第二步这个手机验证完成后,发现还是不能够正常使用,开始注意具体的提示信息,是否真的就只是counter没初始化
因为我的博客是会同步推送到自己的另一个 gitea 服务,最近应该是入口 traefik 的状态有点异常,导致无法同步到gitea服务,但是不影响正常推送到github的page服务
第三步的问题随着这个思考就想到了,因为hexo在部署推送的时候是逐个串行地往目标部署点推送的,比如我有github跟gitea,还有个其他的部署点,那么假如前面gitea的出现了问题,后续的就没法往下推送了,正巧 leancloud 的这个计数服务是通过部署点实现的,在部署日志中会有

1
INFO  Deploying: leancloud_counter_security_sync

那么问题就差不多解决了,只是 traefik 这个问题还要看下,尝试把 traefik 的 docker-compose 启动起来,发现 80 端口被占了,
这时候就又是一个经典问题了,首先是找到哪个进程占用了这个端口

1
lsof -i:80

通过这个命令也可以,当然也可以通过 netstat,只是我一直记不住,用的不太多
发现是这个 apache2,就是重启ubuntu后默认启动的 apache 的 http 服务器,
只是这里需要注意下,它的服务名是 apache2 ,而不是httpd
所以可以通过

1
systemctl stop httpd

来关闭,同时可以用

1
systemctl disable httpd

直接把这个自启动的给干掉,省得每次重启都有这个问题,这一连串的排查还是比较有意思的

之前写了这么一篇标题党,只是这个的确是比较头疼的事情,brew更新了下,php就不能用了,这里面主要是 icu4c 这个库的更新导致的,比如最近我又碰到了
, 正好又解决了下
因为后续brew在 m系列芯片的mac上有了更新,所以之前那篇需要有一些改动,
首先是这个目录 $(brew --prefix)/Homebrew/Library/Taps/homebrew/homebrew-core/Formula
目前这个替换符 $(brew --prefix) 还是有效的,不过路径变更为了 /opt/homebrew,但是后面的路径改变了,变成了 /Library/Taps/homebrew/homebrew-core/Formula
中间少了 Homebrew , 这是第一点,
第二点是对于这个文件 icu4c.rb 的重新安装
因为目前我还在使用 php 7.4 版本,依赖的是 icu4c 的 71 版本,所以就切换到类似于 e3317b86c11c644e88c762e03eb7b310c3337587 这个 commit id 这样,

1
git checkout -b icu4c-71  e3317b86c11c644e88c762e03eb7b310c3337587

但是由于目前的brew已经没有 switch 命令了,所以只能把最新版本的卸载掉,再进行安装老版本
先通过

1
brew uninstall icu4c

卸载老版本的 icu4c
然后再使用

1
brew reinstall ./icu4c.rb

安装 71 版本的,这样就能解决这个问题
第三个问题会在安装时出现
类似于

1
attestation verification failed: Failure while executing; `/usr/bin/env GH_TOKEN=****** /usr/local/bin/gh attestation verify /Users/xxx/Library/Caches/Homebrew/downloads/

这样的操作,可以通过设置常量的形式来解决

1
export HOMEBREW_NO_VERIFY_ATTESTATIONS=true

这样就不去做这个验证了

前两天拜读了章亦春大佬的关于Dynamic Tracing的文章,觉得对现在碰到的一些问题有了一些新的思考,为了能有所产出就先写一点简单的学习记录
首先这个systemtap类似于一个linux系统层面的探针工具,可以让用户去监控系统的各种活动
以阿里云的 ubuntu 22.04 为例,
首先我们需要安装 systemtap-sdt-dev 这个包,
然后因为通过c的方式比较常规,我是想研究下针对像 php 这种怎么去监控
我们需要一个编译参数带上--enable-dtrace 的php版本
然后在编译完后我们写一个简单的测试脚本

1
2
3
4
5
6
<?php
function a($b, $c) {
return $b + $c;
}
sleep(1);
echo a(1, 2);

这其实主要是为了触发系统调用
然后重点就是systemtap的脚本,它有点类似于c的代码,结构主要是 “事件” - “处理器”
比如我监听到了php发起了一个系统调用,那这个时候我想把它记录下来,打印日志这种

1
2
3
4
5
6
probe syscall.*
{
if (execname() == "php") {
printf ("%s(%d) open, call %s \n", execname(), pid(), name)
}
}

这里就是针对所有的系统调用,如果是由php发起调用,那就打印出来pid和系统调用的名字(name就是这里的系统调用名字)

事件

syscall.system_call 只是其中一类事件
还有对虚拟文件系统的操作 vfs.file_operation
内核的方法调用 kernel.function("function")
比如 probe kernel.function("*@net/socket.c") { }
还有可以是内核的一些追踪点
kernel.trace("tracepoint")
比如 kernel.trace("kfree_skb") 这个表示每次当内核中的network buffer被释放的时候触发
还有的是时间时间
timer events
比如

1
2
3
4
probe timer.s(4)
{
printf("hello world\n")
}

每4秒打印一个 hello world
还有这些

1
2
3
4
5
timer.ms(milliseconds)
timer.us(microseconds)
timer.ns(nanoseconds)
timer.hz(hertz)
timer.jiffies(jiffies)

处理器

最常规的一类就是打印信息了
printf ( ) Statements
这个跟c语言也很像,可以用%s%d 作为占位符来填充字符串和数字
然后就是一些定义好的取值方法
execname() (a string with the executable name)
就比如刚才的php,
线程id

1
2
tid()
The ID of the current thread.

用户id

1
2
uid()
The ID of the current user.

比如系统调用就直接用 name
还有很多可以研究,第一篇学习就先到这里

这篇还是javassist的一些使用小技巧,我们可以用javassist来读取java的注解信息
首先我们有这样一个注解

1
2
3
4
public @interface Author {
String name();
int year();
}

注解可以打在类上,那么我们建一个point类

1
2
3
4
@Author(name = "nick", year = 2024)
public class Point {
int x, y;
}

name 是 nick,24年的,

然后我想通过javassist来获取这个类上的注解信息
我们先从对象池中获取这个类

1
CtClass cc = ClassPool.getDefault().get("org.example.Point");

然后获取类上的注解

1
2
Object[] all = cc.getAnnotations();
Author a = (Author)all[0];

将第一个注解强转成Author,因为这里我们知道是只有这个注解,否则可以做的更通用一点
然后把这个主机上的值获取出来

1
2
3
String name = a.name();
int year = a.year();
System.out.println("name: " + name + ", year: " + year);

可以获得结果,非常简单

1
2
3
name: nick, year: 2024

Process finished with exit code 0

为什么讲这么个简单的例子呢,因为这个刚好可以作为一种实现aop的途径,我们可以获取类的信息,包括注解上的,这样我们就可以从源头去理解这些aop啥的可以通过什么方法来实现

0%