macOS Catalina 10.15.x 系统根目录只读问题解决方法

 mac, macpro  macOS Catalina 10.15.x 系统根目录只读问题解决方法已关闭评论
1月 202020
 

macOS Catalina苹果新系统升级了根目录的文件权限,变成只读了,这么做对开发者来说简直就是灾难,好多原来的项目都不能运行了。(我原来用来破解intellidea/pycharm/webstorm的jetbrains-agent.jar 文件放在根目录/data/下,点击intellidea/pycharm/webstorm都无法启动,原来以为是jdk的问题,后来发现就是升级了Catalina新系统后,新系统居然删除了我的/data目录😱😱😱😱😱)

 

解决根目录只读的办法如下:

1. 关掉SIP(系统安全保护)
2. 重新挂载根目录
3. 重新启动项目

具体操作:
一、关掉SIP需要重新启动按住 Command + R 进入 macOS 恢复系统,在实用工具里面点击终端,加上下面这一句代码按下会车,看见successfully…之后重新启动

csrutil disable

二、重新挂载根目录需要在终端输入下面这句代码
sudo mount -uw /

三、最后就可以在根目录创建文件夹了并赋权 sudo mkdir /xxx,sudo chmod 777 /xxx

原来有启动Finder的,最好重启Finder再新建文件夹,让这次允许读写的配置在Finder中生效
killall Finder

macos 10.15.x catalina could not be verified/ xcode 11 An unknown error occurred. See the install log for more details.

 mac, macpro, xcode, 开发  macos 10.15.x catalina could not be verified/ xcode 11 An unknown error occurred. See the install log for more details.已关闭评论
1月 202020
 

2012 macpro  升级 macos 到 10.15.2  catalina  并 安装 新xcode时碰到下列问题,供其他碰到的同学参考。

  • 问题1.  “macOS Catalina” could not be verified, 在”系统偏好设置 ” -> “软件更新”下下载完catalina更新包后点安装,提示  “macOS Catalina” could not be verified.
    解决办法:打开“ 系统偏好设置”->“日期与时间”->去掉打勾”自动设置日期与时间”, 重启机器,并再次软件更新并安装。

Go to settings then date&time. Click and then unclick “set date and time automatically”. Save the changes by clicking the lock.

Then restart the computer and proceed to download the update once again through settings and software update. It resolved the issue of the update not being verified.

 

  • 问题2. macos catalina安装完,打开xcode时,提示“An unknown error occurred. See the install log for more details.”

解决方法:

  • 这个问题再次在Xcode 11.1出现,是有个证书在2019年的10月份某天过期引起的。
  • 你可以通过暂时把系统日期修改到过期的日期之前来解决。
  • 在Xcode 11这个版本下,设置系统日期为2019年10月3日,然后运行Xcode,再安装组件,(就可以安装成功了),完成之后再把系统日期改回正常状态。
  • This problem has once again appeared in Xcode 11.1 and is caused by an invalid certificate that expired some day in October 2019.
  • You can work around the problem by temporarily changing the system date to before the certificate expiration date.
  • In the case of Xcode 11, set the system date to Oct 3, 2019, run Xcode, then change the date back after the components have installed.

苹果公司就这么把版本放出来也是醉了!

 

 

POD 指定版本安装

 pod  POD 指定版本安装已关闭评论
1月 192020
 

pod ‘AFNetworking’ //不显式指定依赖库版本,表示每次都获取最新版本
pod ‘AFNetworking’, ‘~>0’ //高于0的版本,写这个限制和什么都不写是一个效果,都表示使用最新版本

pod ‘AFNetworking’, ‘~> 0.1.2’ //使用大于等于0.1.2但小于0.2的版本
pod ‘AFNetworking’, ‘~>0.1’ //使用大于等于0.1但小于1.0的版本

pod ‘AFNetworking’, ‘2.0’ //只使用2.0版本
pod ‘AFNetworking’, ‘= 2.0’ //只使用2.0版本

pod ‘AFNetworking’, ‘> 2.0’ //使用高于2.0的版本
pod ‘AFNetworking’, ‘>= 2.0’ //使用大于或等于2.0的版本
pod ‘AFNetworking’, ‘< 2.0’ //使用小于2.0的版本
pod ‘AFNetworking’, ‘<= 2.0’ //使用小于或等于2.0的版本

pod ‘AFNetworking’, :git => ‘https://github.com/AFNetworking/AFNetworking.git’, :branch => ‘R20161010’ //指定分支

pod ‘AFNetworking’, :path => ‘../AFNetworking’ //指定本地库

redis数据迁移的3个方法

 redis  redis数据迁移的3个方法已关闭评论
1月 172020
 

1. rdb数据备份恢复方法
redis 127.0.0.1:6379> SAVE
OK
或者
redis-cli -h 127.0.0.1 -p 6379 -a pwd bgsave
该命令将在 redis 安装目录中创建dump.rdb文件。

查找dump.rdb文件位置
redis 127.0.0.1:6379> CONFIG GET dir
1) dir
2) /usr/local/redis/bin
以上命令 CONFIG GET dir 输出的 redis 安装目录为 /usr/local/redis/bin
bgsave
创建 redis 备份文件也可以使用命令 BGSAVE,该命令在后台执行。
127.0.0.1:6379> BGSAVE
Background saving started

2. AOF数据备份恢复方法
另一种持久化方式AOF,在配置文件中打开[appendonly yes]。
AOF刷新日志到disk的规则:
appendfsync always #always 表示每次有写操作都进行同步,非常慢,非常安全。
appendfsync everysec #everysec表示对写操作进行累积,每秒同步一次
官方的建议的everysec,安全,就是速度不够快,如果是机器出现问题可能会丢失1秒的数据。

也可以手动执行bgrewriteaof进行AOF备份:
redis-cli -h 127.0.0.1 -p 6379 -a pwd bgrewriteaof

迁移数据恢复
迁移到另外一台恢复数据,需先检查配置文件,将按照以下优先级恢复数据到内存:
如果只配置AOF,重启时加载AOF文件恢复数据;
如果同时 配置了RBDAOF,启动是只加载AOF文件恢复数据;
如果只配置RBD,启动是讲加载dump文件恢复数据;

dump.rdb或者AOF文件迁移到另外一台恢复数据
恢复数据,只需将备份文件 (dump.rdb或者AOF文件) 移动到 redis 安装目录并启动服务即可。

3. redis从库复制数据方法
Redis提供了复制(replication)功能可以自动实现同步的过程。
配置方法
通过配置文件 从数据库的配置文件中加入slaveof master-ip master-port,主数据库无需配置
通过命令行参数 启动redis-server的时候,使用命令行参数–slaveof master-ip master port
redis-server –port 6380 –slaveof 127.0.0.1 6379
通过命令SLAVEOF master-ip master-port
redis>SLAVEOF 127.0.0.1 6379
SLAVEOF NO ONE可以是当前数据库停止接收其他数据库的同步,转成主Redis数据库,程序连接地址都改为新的redisIP地址和端口。

转自:https://my.oschina.net/ppabvc/blog/819448

ios 9.0/10.0 xcode开发中info.plist文件权限设置

 xcode  ios 9.0/10.0 xcode开发中info.plist文件权限设置已关闭评论
1月 162020
 

iOS9.0的权限设置

iOS9.0引入了新特性App Transport Security (ATS),导致网络请求访问失败,新特性要求App内访问的网络必须使用HTTPS协议,但很多公司使用的还是http协议。

为了让http请求也能正常范文网络数据,解决的办法如下:
在info.plist文件中添加App Transport Security Settings,类型Dictionary;
在App Transport Security Settings下添加Allow Arbitrary Loads类型Boolean,值设为YES;
这里写图片描述

 

iOS10.0对用户的隐私权限越来越重视,要想正常访问相册,相机,位置,麦克风,蓝牙,健康等都需要事先在info.plist文件中进行相应设置,现将开发中常用的用户权限设置总结如下:
蓝牙
NSBluetoothPeripheralUsageDescription
日历
NSCalendarsUsageDescription
相机
NSCameraUsageDescription
健康分享
NSHealthShareUsageDescription
健康更新
NSHealthUpdateUsageDescription
始终允许访问位置
NSLocationAlwaysUsageDescription
位置
NSLocationUsageDescription
在使用期间访问位置
NSLocationWhenInUseUsageDescription
麦克风
NSMicrophoneUsageDescription
运动与健康
NSMotionUsageDescription
相册
NSPhotoLibraryUsageDescription
提醒事项
NSRemindersUsageDescription

方式一:使用属性列表方式修改:

方式二:源文件方式

<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>NSContactsUsageDescription</key>
<string>请求访问通讯录</string>
<key>NSMicrophoneUsageDescription</key>
<string>请求访问麦克风</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>请求访问相册</string>
<key>NSCameraUsageDescription</key>
<string>请求访问相机</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>始终访问地理位置</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>在使用期间访问地理位置</string>
<key>NSCalendarsUsageDescription</key>
<string>请求访问日历</string>
<key>NSRemindersUsageDescription</key>
<string>请求访问注意事项</string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>请求访问蓝牙</string>

 

swift内存管理中WEAK 和 UNOWNED介绍与使用

 swift  swift内存管理中WEAK 和 UNOWNED介绍与使用已关闭评论
1月 062020
 

网上看到的一篇关于swift 的内存管理的weak和unowned介绍和使用的文章,觉得写的挺好,分享下。文章来源地址: onevcat

 

不管在什么语言里,内存管理的内容都很重要,所以我打算花上比其他 tip 长一些的篇幅仔细地说说这块内容。

Swift 是自动管理内存的,这也就是说,我们不再需要操心内存的申请和分配。当我们通过初始化创建一个对象时,Swift 会替我们管理和分配内存。而释放的原则遵循了自动引用计数 (ARC) 的规则:当一个对象没有引用的时候,其内存将会被自动回收。这套机制从很大程度上简化了我们的编码,我们只需要保证在合适的时候将引用置空 (比如超过作用域,或者手动设为 nil 等),就可以确保内存使用不出现问题。

但是,所有的自动引用计数机制都有一个从理论上无法绕过的限制,那就是循环引用 (retain cycle) 的情况。

什么是循环引用

虽然我觉得循环引用这样的概念介绍不太应该出现在这本书中,但是为了更清晰地解释 Swift 中的循环引用的一般情况,这里还是简单进行说明。假设我们有两个类 A 和 B, 它们之中分别有一个存储属性持有对方:

class A {
    let b: B
    init() {
        b = B()
        b.a = self
    }

    deinit {
        print("A deinit")
    }
}

class B {
    var a: A? = nil
    deinit {
        print("B deinit")
    }
}

在 A 的初始化方法中,我们生成了一个 B 的实例并将其存储在属性中。然后我们又将 A 的实例赋值给了 b.a。这样 a.b 和 b.a 将在初始化的时候形成一个引用循环。现在当有第三方的调用初始化了 A,然后即使立即将其释放,A 和 B 两个类实例的 deinit 方法也不会被调用,说明它们并没有被释放。

var obj: A? = A()
obj = nil
// 内存没有释放

因为即使 obj 不再持有 A 的这个对象,b 中的 b.a 依然引用着这个对象,导致它无法释放。而进一步,a 中也持有着 b,导致 b 也无法释放。在将 obj 设为 nil 之后,我们在代码里再也拿不到对于这个对象的引用了,所以除非是杀掉整个进程,我们已经永远也无法将它释放了。多么悲伤的故事啊..

在 Swift 里防止循环引用

为了防止这种人神共愤的悲剧的发生,我们必须给编译器一点提示,表明我们不希望它们互相持有。一般来说我们习惯希望 “被动” 的一方不要去持有 “主动” 的一方。在这里 b.a 里对 A 的实例的持有是由 A 的方法设定的,我们在之后直接使用的也是 A 的实例,因此认为 b 是被动的一方。可以将上面的 class B 的声明改为:

class B {
    weak var a: A? = nil
    deinit {
        print("B deinit")
    }
}

在 var a 前面加上了 weak,向编译器说明我们不希望持有 a。这时,当 obj 指向 nil 时,整个环境中就没有对 A 的这个实例的持有了,于是这个实例可以得到释放。接着,这个被释放的实例上对 b 的引用 a.b 也随着这次释放结束了作用域,所以 b 的引用也将归零,得到释放。添加 weak 后的输出:

A deinit
B deinit

可能有心的朋友已经注意到,在 Swift 中除了 weak 以外,还有另一个冲着编译器叫喊着类似的 “不要引用我” 的标识符,那就是 unowned。它们的区别在哪里呢?如果您是一直写 Objective-C 过来的,那么从表面的行为上来说 unowned 更像以前的 unsafe_unretained,而 weak 就是以前的 weak。用通俗的话说,就是 unowned 设置以后即使它原来引用的内容已经被释放了,它仍然会保持对被已经释放了的对象的一个 “无效的” 引用,它不能是 Optional 值,也不会被指向 nil。如果你尝试调用这个引用的方法或者访问成员属性的话,程序就会崩溃。而 weak 则友好一些,在引用的内容被释放后,标记为 weak 的成员将会自动地变成 nil (因此被标记为 @weak 的变量一定需要是 Optional 值)。关于两者使用的选择,Apple 给我们的建议是如果能够确定在访问时不会已被释放的话,尽量使用 unowned,如果存在被释放的可能,那就选择用 weak

我们结合实际编码中的使用来看看选择吧。日常工作中一般使用弱引用的最常见的场景有两个:

  1. 设置 delegate 时
  2. 在 self 属性存储为闭包时,其中拥有对 self 引用时

前者是 Cocoa 框架的常见设计模式,比如我们有一个负责网络请求的类,它实现了发送请求以及接收请求结果的任务,其中这个结果是通过实现请求类的 protocol 的方式来实现的,这种时候我们一般设置 delegate 为 weak

// RequestManager.swift
class RequestManager: RequestHandler {

    @objc func requestFinished() {
        print("请求完成")
    }

    func sendRequest() {
        let req = Request()
        req.delegate = self

        req.send()
    }
}

// Request.swift
@objc protocol RequestHandler {
    optional func requestFinished()
}

class Request {
    weak var delegate: RequestHandler!;

    func send() {
        // 发送请求
        // 一般来说会将 req 的引用传递给网络框架
    }

    func gotResponse() {
        // 请求返回
        delegate?.requestFinished?()
    }
}

req 中以 weak 的方式持有了 delegate,因为网络请求是一个异步过程,很可能会遇到用户不愿意等待而选择放弃的情况。这种情况下一般都会将 RequestManager 进行清理,所以我们其实是无法保证在拿到返回时作为 delegate 的 RequestManager 对象是一定存在的。因此我们使用了 weak 而非 unowned,并在调用前进行了判断。

闭包和循环引用

另一种闭包的情况稍微复杂一些:我们首先要知道,闭包中对任何其他元素的引用都是会被闭包自动持有的。如果我们在闭包中写了 self 这样的东西的话,那我们其实也就在闭包内持有了当前的对象。这里就出现了一个在实际开发中比较隐蔽的陷阱:如果当前的实例直接或者间接地对这个闭包又有引用的话,就形成了一个 self -> 闭包 -> self 的循环引用。最简单的例子是,我们声明了一个闭包用来以特定的形式打印 self 中的一个字符串:

class Person {
    let name: String
    lazy var printName: ()->() = {
        print("The name is \(self.name)")
    }

    init(personName: String) {
        name = personName
    }

    deinit {
        print("Person deinit \(self.name)")
    }
}

var xiaoMing: Person? = Person(personName: "XiaoMing")
xiaoMing!.printName()
xiaoMing = nil
// 输出:
// The name is XiaoMing,没有被释放

printName 是 self 的属性,会被 self 持有,而它本身又在闭包内持有 self,这导致了 xiaoMing 的 deinit 在自身超过作用域后还是没有被调用,也就是没有被释放。为了解决这种闭包内的循环引用,我们需要在闭包开始的时候添加一个标注,来表示这个闭包内的某些要素应该以何种特定的方式来使用。可以将 printName 修改为这样:

lazy var printName: ()->() = {
    [weak self] in
    if let strongSelf = self {
        print("The name is \(strongSelf.name)")
    }
}

现在内存释放就正确了:

// 输出:
// The name is XiaoMing
// Person deinit XiaoMing

如果我们可以确定在整个过程中 self 不会被释放的话,我们可以将上面的 weak 改为 unowned,这样就不再需要 strongSelf 的判断。但是如果在过程中 self 被释放了而 printName 这个闭包没有被释放的话 (比如 生成 Person 后,某个外部变量持有了 printName,随后这个 Persone 对象被释放了,但是 printName 已然存在并可能被调用),使用 unowned 将造成崩溃。在这里我们需要根据实际的需求来决定是使用 weak 还是 unowned

这种在闭包参数的位置进行标注的语法结构是将要标注的内容放在原来参数的前面,并使用中括号括起来。如果有多个需要标注的元素的话,在同一个中括号内用逗号隔开,举个例子:

// 标注前
{ (number: Int) -> Bool in
    //...
    return true
}

// 标注后
{ [unowned self, weak someObject] (number: Int) -> Bool in
    //...
    return true
}

debian/ubuntu/centos一键搭建openvpn服务器

 openvpn  debian/ubuntu/centos一键搭建openvpn服务器已关闭评论
12月 312019
 

想搭个个人用的openvpn服务器,网上看到大大分享了个一键搭建openvpn的脚本,适用于 Debian, Ubuntu 和 CentOS,测试了Debian和centos系统,果然好用!!!!(源码项目github地址)

安装步骤:

命令行运行: wget https://git.io/vpn -O openvpn-install.sh && bash openvpn-install.sh

按照提示一步步往下走, 设置ip 、 tcp/udp选择、dns、端口、新增客户端ovpn文件名等。

如果后期需要删除原来的用户或新增新用户或删除openvpn等操作可以再次运行openvpn-install.sh脚本,根据提示进行对应操作即可,实在太方便了,给个大大的👍!!

xcode运行提示”Install claimed to have succeeded, but application could not be found on device…”

 开发  xcode运行提示”Install claimed to have succeeded, but application could not be found on device…”已关闭评论
12月 302019
 

xcode 11真机运行时提示”Install claimed to have succeeded, but application could not be found on device”,可以试验下方法:

  • 方法一:Product -> Clean;close xcode(关闭xcode);reopen xcode再重新打开(呵呵,我的竟然就是这么解决的,就是这么神奇!)
  • 方法二:File > Project Settings… > Build System > Legacy Build System

还可以尝试下下面链接中的各个方法:https://stackoverflow.com/questions/56229960/track-google-play-refunds-performed-by-user-google

mac os使用tunnelblick作为openvpn客户端

 mac  mac os使用tunnelblick作为openvpn客户端已关闭评论
12月 302019
 

openvpn官网有对应的windows客户端可以下载,但没有mac os的对应版本,而Tunnelblick 是适用于Mac OS X 的OpenVPN Client 的一个GUI 版本,相当好用。

下面介绍下Tunelblick的安装和配置:

1. 安装 Tunnelblick

从以下链接下载和安装 Tunnelblick。

https://tunnelblick.net/downloads.html#releases

选择stable稳定版,我这里选择的Tunnelblick3.8.1

 

2. 双击打开

将配置文件xxx.ovpn 按下图拖入配置框

完成后点击“连接”

 

网络上也有一些免费的公共vpn配置文件可以下载,但稳定性和有效性就自己考量了。

OpenVPN 连接设置文件(.ovpn)从 公共 VPN 中继服务器列表页面 下载。

gcp中为debian系统修改时区

 gcp  gcp中为debian系统修改时区已关闭评论
12月 272019
 

google cloud platform机器开了美国的vm,发现时区不对,如果对debian系统的时区做修改

两种方法

一、 使用dpkg-reconfigure修改

o-u-u#  dpkg-reconfigure tzdata

该操作会修改两个文件:

/etc/timezone #该文本文件可直接修改
/etc/localtime #该文件可通过软链接修改

二、手动修改以上两个文件

o-u-u# vim /etc/timezone
Asia/Shanghai

o-u-u# ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
或者
o-u-u# cp -a /usr/share/zoneinfo/Asia/Shanghai /etc/localtime