前言
此篇博文是笔者所总结的 Macos 系列之一;
本文为作者的原创作品,转载需注明出处;
find port and kill
经常我们需要有在命令行执行 kill 的场景,比如,莫名其妙的某个端口被占用了
比如,本机的 4000 端口被某个不知道的进程所占用,这个时候,如何找到并将其 kill 掉呢?
使用 netstat
1
2
3
4
5
6$ netstat -vanp tcp | grep 4000
tcp4 645 0 127.0.0.1.4000 127.0.0.1.57534 ESTABLISHED 408300 146988 37177 0
tcp4 0 0 127.0.0.1.57534 127.0.0.1.4000 ESTABLISHED 408300 146988 759 0
tcp4 664 0 127.0.0.1.4000 127.0.0.1.57533 CLOSE_WAIT 408300 146988 37177 0
tcp4 0 0 127.0.0.1.57533 127.0.0.1.4000 FIN_WAIT_2 408300 146988 759 0
tcp4 0 0 *.4000 *.* LISTEN 131072 131072 37177 0这样,通过上述的命令便知道了,4000 端口是被 37177 这个进程占用了,只需要将其 kill 即可
1
$ kill -9 37177
https://stackoverflow.com/questions/3855127/find-and-kill-process-locking-port-3000-on-mac
使用 lsof
1
lsof -i:80
-i
参数表示网络链接,:80
指明端口号,该命令会同时列出PID,方便kill
按键
常用按键
⌘ —— Command ()
⌃ —— Control
⌥ —— Option (alt)
⇧ —— Shift
⇪ —— Caps Lock
fn—— 功能键就是fn
自定义某个应用的快捷键
今天在使用 Note 做编辑的时候,发现其它的快捷键都有,就是没有 Strikethrough 的快捷键,而我有大量的行需要使用到 Strikethrough,造成很大的不变,因此,我需要自定义 Note 的快捷键,
- 选择 App Shortcuts
- 选择你要设置的应用,这里我选择 Note.app
- 选择你要设置的功能的名称,一定要和你的 app 中所定义的功能名称对应,这里我需要设置 Strikethrough 的快捷键,自然输入的就是 Strikethrough
Command 中切换用户
切换至 ROOT 用户
1 | $ sudo -i |
切换回普通用户
1 | $ su - mac |
JVM
安装地址
/Library/Java/JavaVirtualMachines/jdk1.7.0_79.jdk/Contents/Home
备注,只要是通过官网默认的 dmg 安装包进行安装的,就会默认安装到这个目录中;
修改环境变量
必须同时修改 ~/.bash_profile 和 ~/.profile 两个文件,这样,重新看起一个终端的时候,才会使用新的 jvm。
小技巧
我的电脑型号
2014 款 macbook,
2014 rMBP机身重量为3.46磅,屏幕分辨率为2,560 x1,600,像素密度为227ppi。设备上的接口也没有变化,左边分别是MagSafe 2充电口、两个Thunderbolt 2接口、一个USB 3.0接口、3.5mm耳机接口以及两个麦克风孔;右边也有一个USB 3.0接口、一个HDMI输出口以及全尺寸SD卡槽
可见, Thunderbolt 2 以及 Thunderbolt 1 使用的接口型号是 Mini DP,所以,可以认为,两个其实就是同一个东西。
外接 4K 显示器
http://bbs.itools.cn/thread-98257-1-1.html
苹果在2013年开始使用2代雷电技术,其支持DisplayPort 1.2(17.28Gbps)。也就是说:late 2013或者更新的mac使用的是2代雷电接口,并且能支持1个在60Hz的4k显示器。如果有独显,那就是同时输出多个了(最主要还是看你显卡)。
从作者的描述中可以看到,只要是使用 2 代的 thundbolt,转成 DP 1.2,就可以支持 60Hz 的 4K 输出。可以试试。
DNS 检查
今天遇到一个奇怪的事情,HRX 官网地址之前映射在 119.23.xxx.xx UAT 地址上,可是后来,将域名映射为 39.108.xx.xxx PROD 地址上以后,域名服务提供商确认映射 OK 了,可是我本地的域名映射却始终指向的是 UAT 的地址,也通过 Flushing your DNS cache in Mac OS X and Linux 的步骤清理掉本机上的 DNS 缓存,可是还是不行.. 但是在远方的同事(不在同一个局域网)却能够正确的解析到 PROD 地址上;纳里,这时怎么回事,看来必须得对 OSX 的域名解析了解下了
1 | $ nslookup www.hrx.com |
可以看到,hrx 的域名的确还是被映射到的 UAT 的地址,可是,问题是,域名解析在 DNS 服务商那里改变了呀…
注意这行Server: 192.168.31.1
,192.168.31.1 似曾相似,这不就是我的小米路由器嘛.. Ok,顿时焕然大悟,原来,我本机现在使用的是路由器进行的 DNS 解析,所以,要做的不是去 flush 本机上的 DNS cache,而是应该去 Flush 小米路由器上的 DNS 缓存才能生效;Ok,这下搞明白了..
另外,可以直接通过查看 /etc/resolv.conf 查看本机 DNS 解析器,
1 | $ cat /etc/resolv.conf |
192.168.31.1 既是 DNS Server…
Chrome 对应的快捷键
command + R: 刷新
command + shift + R: 强制刷新
查看隐藏文件
如果要查看隐藏文件,在控制终端输入如下的命令,1
$ defaults write com.apple.finder AppleShowAllFiles TRUE
不过,这个时候,如果文件夹是打开的或者是激活的状态,是不会立即生效的,执行如下命令,1
$ killall Finder
将当前的所有 Finder 杀死,然后启动 Finder,则可以看到所有的隐藏文件了;如果要不显示隐藏文件,输入如下命令即可,1
$ defaults write com.apple.finder AppleShowAllFiles False
Reference: https://www.howtogeek.com/211496/how-to-hide-files-and-view-hidden-files-on-mac-os-x/
什么时候买合适
一个专门的网站告诉你什么是入手新的苹果是最佳的时机?
https://buyersguide.macrumors.com/
iTerms
下载
iTerms 是取代 macos 默认的 Terminal 的利器,下载地址,https://www.iterm2.com/downloads.html
配色方案
默认启动的时候,iTerms 是没有任何配色方案的,通过下面的步骤,启动 iTerms 的配色方案,
修改 _bash_profile_
1
> vim ~/.bash_profile
添加如下的内容,
1
2
3
4
5
6
7
8
9
10#enables colorin the terminal bash shell export
export CLICOLOR=1
#setsup thecolor scheme for list export
export LSCOLORS=gxfxcxdxbxegedabagacad
#sets up theprompt color (currently a green similar to linux terminal)
#export PS1='\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;36m\]\w\[\033[00m\]\$ '
#enables colorfor iTerm
export TERM=xterm-256color添加 .vimrc
1
2
3syntax on
set number
set ruler这一步的目的是,在使用 vim 编辑器的时候,会显示配色方案;
- 重新加载 .bash_profile 激活
1
> source ~/.bash_profile
这样,当你再次输入命令的时候,配色方案就生效了,如下图所示,
选择不同的背景
iTerm2 -> Preferences -> Profiles -> Colors -> Color Presets:
导入其它的背景
iTerm2 -> Preferences -> Profiles -> Colors -> Color Presets -> Imports
Github 上有许多的背景,比如 Peppermint: https://github.com/dotzero/iTerm-2-Peppermint ,比如官网上的 http://iterm2colorschemes.com/
字体调整
修复
重启后,远程登录设置被重置
每次重新启动以后,远程登录选项的设置都被重置,被关闭;这对于使用 macos 作为服务器的用户来说,是个噩梦,想想,一旦服务器自动重启后,却无法通过 ssh 远程登录,是何感想;这个问题非常的扰人,就我的 imac 出现这个问题,自己的 macbook 没有这个问题,可见,这个并非是苹果的特殊设置;关于这个问题讨论得非常的少,唯一的就是这篇 https://discussions.apple.com/thread/7147813 文章从头至尾的在讨论,有人通过下面的方法解决了,
“I renamed each original .plist file to “.plistOLD,” then dragged the edited .plist to its appropriate folder. Then, I used the latest beta of BatChmod (1.7 beta 5 at this writing) to change the ownership of each edited .plist to “root,” gave “root” and the “Administrators” group Read/Write permission, and the Everyone group Read (only) permission. After a restart, the File Sharing and Screen Sharing checkboxes remained checked.”
这个牛人是按个查找系统里面的所有的 .plist 文件,然后将它的权限赋给 Root,同时使得 “Administrators” group 用户读写权限,然后,不断的重启试验,然后在某一次,重启后,他成功了;不过这给了我启发,一定是某个重要文件的权限出了问题,导致系统重启后,相关账户,Root 或者 Administor 用户没有权限设置系统为之前的状态,因此导致了这个状态设置(远程登录状态设置)在每次重启的时候丢失了;
回想了下,自己很有可能就是在安装 Homebrew 的时候,听信了网上设置 /usr/local 权限的解决办法,执行了下面的语句,
1 sudo chown -R $(whoami) $(brew --prefix)/*
执行了之后,该命令很猛,扫描了系统的所有文件,然后将所有的系统文件的所有权赋值给了当前用户,God,一定是这样导致的;上面的解决办法出自 https://github.com/Homebrew/brew/issues/3228 但是他所解决的问题是,之前一定要先安装好了 Homebrew 的用户才能使用的方法,它是去找所有与 brew 相关的文件,然后添加用户权限;但是如果,现在你是一个并没有安装 Homebrew 的用户呢?想想它会返回什么?对的是,
/*
,因此,就是这一行命令,让我把系统文件所有的权限都给改了;天煞的……
所以,如果上面的问题不解决,那么还会有更多的奇奇怪怪的问题出现,因此,只能抹盘
并重装系统了
;记得一定要抹盘后安装;
最后,经过个把小时的系统重装,设置远程登录后再次重启,重启后,远程登录的状态便不再丢失了~~~
急救
忘记用户名密码?
重装系统忘记了管理员用户密码,怎么办?进入 root 命令环境,删除用户 db 设置,重启,重新设置管理员用户;
- 重启,一直按着 COMMAND + S 不松手,直到出现 root 命令行
- 然后依次执行如下命令,
1
2
3
4
5fsck -y
mount -uaw /
# 删除设置数据库
rm /var/db/.AppleSetupDone
reboot
这样,重启以后就会重新进入用户设置页面了;
/etc/sudoers is owned by uid 501, should be 0
这个错误直接导致 sudo 不能使用,同样需要重启系统进入 root command 环境,然后对 /etc/sudoers 文件的权限进行修复;步骤如下
- 重启,一直按着 COMMAND + S 不松手,直到出现 root 命令行
然后依次执行如下命令进行修复
1
2
3
4
5fsck -fy
mount -uw /
chown root:wheel /etc/sudoers
chmod 440 /etc/sudoers
reboot默认情况下,/etc/sudoers 必须属于 root,并且必须属于 wheel 工作组,权限也必须为 440,恢复 /etc/sudoers 的默认设置;重启以后,sudo 正常工作;
cron and crontab
本章节主要描述,在 macos 系统下如何创建 cron job;
概念
首先要明确两个概念,cron 和 crontab,
- cron
cron 准时启动由 crontab 所定义的命令;cron 是通过 launchd 随开机自启动而启动的,无需手动启动,cron 会每隔 1 分钟检查 crontab 的状态,看是否有新增的 crontab job,如果有,则加载进内存,并且按照 crontab 所定义的时间执行相应的 job;所以,总结起来就是,只要 crontab 将 job 定义好了以后,cron 便会自动的将这些 job 加载并在规定时刻执行,无需我们队 cron 进行任何管理; - crontab
该命令定义由 cron 执行的 job;那么如何定义,参考 crontab 小节;
crontab
时间定义
触发时间定义
在定义 cron job 的时候,首先要定义的是 job 执行的时刻,看一个最简单的例子1
0 0,12 1 2 * /sbin/ping -c 192.168.0.1 >> ~/tmp/ping.out
可见,最开始对应了 5 个参数,分别是 0
、0,12
、1
、2
和 *
,那么这 5 个参数按照先后顺序依次对应如下的 field,1
2
3
4
5
6
7field allowed values
----- --------------
minute 0-59
hour 0-23
day of month 1-31
month 1-12 (or names, see below)
day of week 0-7 (0 or 7 is Sun, or use names)
所以,上面所定义的 cron job 的意思就是说,在每年的 2 月份的第 1 天,分别在凌晨 12 点和中午 12 点的 0 分的时候开始 ping,并将 ping 的结果输出到日志中;上面使用到了两个特定的符号,一个是 *
,表示的是任意值,一个是,
,表示的是数组,上面的参数 0,12 表示的就是由值 0 和 12 所构成的数组,在时间表达式中表示分别在这两个时间执行;
四个特殊的符号
cronjob 总共有四个特殊的符号,摘自 https://crontab.guru/
1 | opr description |
*
any value
这个没有什么好多说的,任意值,换句话说,取值范围之内的值都符合;,
value list separator
如果 month 设置为 *,将 day 的表达式写成2,10
,表示分别在每个月的第 2 天或第 10 天执行;-
range of values 范围表达式符号
如果 #2 的表达式改成-
,2-10
,则表示从每个月的第 2 天开始直到第 10 天结束,每天都执行;/
step values 不仅表达式
这个是最不好理解的,/
后接数字,既步长,表示递进多少步长取值,举例,以 hour 定义为例,表达式0-23/2
的实际取值转换为 value list speparator 等价于0,2,4,6,8,10,12,14,16,18,20,22
,上面的意思就是每个两小时执行一次,因此步长是 2 小时;上面的表达式也可以写成*/2
,两者等价;当然,如果你想说,我想在规定的时间段内,每个两小时执行一次,可以写成0-12/2
,这就表示从凌晨 12 点开始直到中午 12 点,每个两小时执行一次;不过要特别特别注意的是,/
默认在起始值要执行一次,比如0-23/2
,在 0 点要执行一次;
@reboot
该命令只在系统重启后执行一次,且只执行一次;该命令非常有用,比如一些需要在系统启动后初始化执行的 bash command 就可以在这里定义了;看一个最简单的例子,1
@reboot /bin/echo "computer started!" >> ~/tmp/start.out`
那么意思就是说,在每次开机的时候执行 ping 并输出到日志文件中,并且仅执行一次;
一些复杂的例子
1 | 0 0,12 1 */2 * /sbin/ping -c 192.168.0.1 >> ~/tmp/ping.out |
表示,在每间隔 1 个月(步长 2)的第 1 天的早上 12:00am 和中午 12:00pm 的时候执行一次;
创建和编辑
使用 crontab -e
要创建 crontab 很简单,直接使用命令 crontab -e 并输入命令即可;
小记,自己在试验的时候,直接使用 crontab -e 并没有初始化创建成功,crontab -e 默认使用的是 vim 编辑器,而是使用了 nano 编辑器才成功,
1 env EDITOR=nano crontab -e
编辑好以后,使用 CTRL + T 存储内容,CTRL + X 退出即可;但是,当初始化成功以后,就可以使用 crontab -e 的 vim 编辑器进行编辑和保存了;
为了测试方便,可以首先创建一个每分钟都会执行一次的命令,输入如下内容,1
* * * * * /sbin/ping www.baidu.com >> ~/tmp/ping.out
保存,即可;这里尤其要注意的是,cron 并不会读取你的 profile 和系统中所定义的环境变量,因此,你需要手动的指定命令的位置;为了减少复杂性,可以直接在 crontab 命令的开始处中添加如下的内容导入环境变量,然后上面的测试用例就可以写成如下的方式;1
2
3
PATH=/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:~/bin
* * * * * ping www.baidu.com >> ~/tmp/ping.out
使用 bash
1 | export JOB_MINUTES=4 |
-
表示使用 crontab 使用标注输入,也就是左侧管道的返回值;这样,就可以动态的定制 crontab 了;
https://askubuntu.com/questions/880052/how-can-i-change-crontab-dynamically
查看
查看命令是否创建或编辑成功,1
2$ crontab -l
* * * * * /sbin/ping www.baidu.com >> ~/tmp/cron.out
如果输出了刚才所创建的命令,表示创建成功!
作用范围
cron job 只对当前用户有效,cron job 一旦创建,该 job 的 owner 是当前用户,只有当前用户或者 root 才有权限执行,并且 bash 的相对路径是当前用户,命令中可以使用 $HOME 或者 ~ 指向用户的根目录;
何时启动
cron job 和 launchctl 不同,launchctl 要求必须是在用户通过 GUI logged in 以后(称作 login session )才能执行,而 cron job 不受这个限制,即便是用户不登录一样可以执行;所以,它的命令只要系统启动,便可以执行,也可以理解为它的脚本是在 Start Up Session 开始执行的;
为了印证上述的论断,笔者做了一个小小的测试,在不登录当前用户的情况下,执行如下的 crontab1
2
3
PATH=/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:~/bin
* * * * * echo "hello!" >> ~/tmp/ping.out
每分钟像 ping.out 中写入一个字符串 “hello!”,10 分钟以后登录,发现 ping.out 中已经写满了 10 个 “hello!”;所以可以断定,cron 的任何 job 都不需要登录后执行;
https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/Introduction.html 介绍了苹果启动执行的生命周期;
reference
Specification: https://www.pantz.org/software/cron/croninfo.html
bash
使用 Terminal 创建、删除用户
当使用 macos 作为服务器的时候,难免会使用到命令行的方式来创建用户,创建用户的方式有两种,一种是普通用户,一种是 admin 用户;有两种流行的方式来创建,一种是使用 dscl 命令,一种是使用 sysadminctl 命令;
- dscl 命令非常的细,细到可以设置用户的 UniqueID 等等,设置非常的繁琐,而且这些信息往往都是我们不关注的,相关内容查看 https://apple.stackexchange.com/questions/226073/how-do-i-create-user-accounts-from-the-terminal-in-mac-os-x-10-11
- sysadminctl 命令就简单了许多了,封装了非常多不必要的复杂性,从它的帮助文档中可以看到,
1
2
3
4
5
6$ sysadminctl help
-adminUser <admin user name> -adminPassword <admin user password>
-deleteUser <user name> [-secure || -keepHome] (interactive || -adminUser <administrator user name> -adminPassword <administrator password>)
-newPassword <new password> -oldPassword <old password> [-passwordHint <password hint>]
-resetPasswordFor <local user name> -newPassword <new password> [-passwordHint <password hint>] (interactive] || -adminUser <administrator user name> -adminPassword <administrator password>)
-addUser <user name> [-fullName <full name>] [-UID <user ID>] [-shell <path to shell>] [-password <user password>] [-hint <user hint>] [-home <full path to home>] [-admin] [-picture <full path to user image>] (interactive] || -adminUser <administrator user name> -adminPassword <administrator password>)
创建普通用户
创建一个普通用户 <username>;
1
sysadminctl -addUser <username>
将其加入 /etc/sudoers,失败,即便是使用当前系统唯一的系统管理员都不可以;说是没有权限;看来,通过命令行的方式将用户加入 sudoers 被堵死了;估计只能进入 root Shell 环境才可以了;
那么,如果要切换到刚创建的 <username> 上呢?记得一定要使用 sudo,否则不成功
1
sudo su - <username>
如果直接,是不会成功的;
1
su - <username>
创建 admin 用户
从 syadminctl 的帮助文档中可以看到,命令是通过 -adminUser 来创建的,不过没试;
删除用户
通过 sysadminctl 删除
下面的命令删除上面所创建的普通用户 <username> 失败,1
sysadminctl -deleteUser <username\>
错误是,系统认为用户 <username> 是拥有 SecureToken 的用户,不能使用命令行通过 syadminctl 直接删除;
- 通过 System Preferences $\to$ User & Groups 却能删除成功;从这里可以看到,MacOS 的定位了,它是偏向桌面应用的,命令行的功能上有所削弱,或者说,通过命令行在功能上有比较大的限制;
修改密码
1 | syadminctl -resetPasswordFor <username> -newPassword xxx ... |
也失败,得到的错误是,Operation is not permitted without secure token unlock! 这里突然提到这么一个新的概念,secure token,错误的意思是,secure token 没有解锁的情况下,是不允许这么操作的;那这个 Secure Token 是干嘛的呢?见下一小节
Security Token
摸索
在执行相关命令的时候,总是报错1
2$ sysadminctl -secureTokenOn shangyang -password comedsh006
2018-10-19 11:27:52.966 sysadminctl[3069:148374] Operation is not permitted without secure token unlock.
意思是,如果想要执行上述命令,必须解锁 secure token;
按照 mac 的官方说法是,第一个被创建的 admin 用户会自动的分配一个 secure token,但是,我检查的情况是没有,
1 | $ sysadminctl -secureTokenStatus <admin> |
Security Token,
浅显易懂,总结得非常好,https://www.linkedin.com/pulse/high-sierra-secure-token-sysadminctl-alex-kaloostian/
https://derflounder.wordpress.com/2018/01/20/secure-token-and-filevault-on-apple-file-system/
总结
从上述的内容分析可知,Secure Token 是 10.13 版本,苹果新增的一个特性,主要是为了 FileVault 工具所设计的,System Preferences $\to$ Security & Privacy $\to$ FileVault 进入,从该工具的描述内容可知,它是用来对磁盘内容进行加密的,而这个加密工具,需要一个额外的权限,就是这个 Secure Token;
并且从官方文档的介绍中说明,该 Secure Token 不需要用户自行设置,在系统安装的时候,随着第一个管理员创建的时候,就会生成一个默认的 Secure Token 并赋给该管理员账号;但是通过 -secureTokenStatus 检查,imac 的默认管理员账号的 secureToken 是 DISABLE 的,并且我的 macbook 的默认系统管理员的 secureToken 默认也是 DISABLE 的;这就匪夷所思了,到底是没创建还是没激活 Secure Token?
总结
不难看出,通过 ssh 命令行创建用户的方式限制颇多,但是一旦进入桌面应用以后,所有的限制就都没有了;所以,这里务必要认识到,MacOS 是定位为一个桌面系统而非 Server,有这样的限制,也不足为其了;所以,如果必须要使用 MacOS 作为服务器,最好是通过桌面端创建好所需要的用户;但是,如果我需要批量的通过 SSH 命令初始化用户的话,就没辙了,至少,笔者没摸索出可行的方案;