在OSX上启动Bash脚本的速度非常慢

时间:2017-03-23 20:31:22

标签: bash macos

我遇到的问题是我的bash脚本需要很长时间才能启动。起初我认为这是脚本本身的一些东西,但是一个快速的实验反驳了这一点。

这是示例脚本

#!/bin/bash
echo 'ping'

我跑的时候

$ time ./script.sh

我得到了

ping

real    0m12.018s
user    0m0.002s
sys    0m0.002s

(我甚至看到它上升到17秒......)令人难以置信的是,当我第二次运行时,它会立即发生。

ping

real    0m0.004s
user    0m0.002s
sys 0m0.002s

但是当我再次编辑文件时,它又回到漫长的等待中。

$ echo 'echo test' >> gbr.sh
$ time ./gbr.sh
ping
test

real    0m13.021s
user    0m0.003s
sys 0m0.003s

这几乎就像bash正在编译我的脚本或其他东西。 有没有办法调试这个?它似乎与我的.bash_profile没什么关系 - 如果我只是在.bash_profile的第一行放回一个回音我仍然只看到10秒以后。

我在iTerm2和原生终端中尝试过这个问题 - 两者都有完全相同的问题。这是在macOS Sierra - 10.12.3

2 个答案:

答案 0 :(得分:3)

我的工作机器上遇到了同样的问题,运行macOS Sierra 10.12.5和10.12.6,我确认@ charles-duffy是对的。我公司的反恶意软件就是问题所在。他们正在使用一个名为Confer by Carbon Black的守护进程来实现端点安全。

运行此命令以查看问题是否停止:

launchctl unload /Library/LaunchDaemons/com.confer.sensor.daemon.plist

我认为Confer正在对其看到的每个新程序进行指纹测试,并尝试在允许其运行之前将其与黑名单进行比较。看起来它在一秒钟之后超时(试图在线注册指纹?),并且有些东西让它一遍又一遍地尝试,产生更长的整数秒延迟。这使得新修改的程序启动缓慢,但在指纹完成后速度恢复正常。

示例运行

以下是我的笔记本电脑上出现的问题。随着时间的推移,有时延迟会增加,但一次总是按整数秒。如果Confer记得之前的节目,就不会有任何延迟。

bash脚本

$ bash --norc --noprofile -l  # make sure rc scripts don't interfere

bash-3.2$ echo exit > exit.sh && chmod +x exit.sh

bash-3.2$ time ./exit.sh

real    0m1.004s
user    0m0.001s
sys 0m0.002s

bash-3.2$ time ./exit.sh

real    0m0.002s
user    0m0.001s
sys 0m0.001s

运行提供给bash -c的命令没有问题:

bash-3.2$ time bash -c exit

real    0m0.008s
user    0m0.002s
sys 0m0.003s

awk脚本

但问题确实影响了awk脚本:

bash-3.2$ printf '%s\n' '#!/usr/bin/env awk -f' 'BEGIN { exit 0; }' > test.awk && chmod +x test.awk

bash-3.2$ time ./test.awk

real    0m4.010s
user    0m0.002s
sys 0m0.001s

bash-3.2$ time ./test.awk

real    0m0.005s
user    0m0.002s
sys 0m0.001s

编译的二进制文件

它甚至影响了编译的C和Golang代码:

bash-3.2$ printf '%s\n' '#include "stdio.h"' 'int main() {' 'printf("Hello, world!\n");' 'return 0;' '}' > hello.c && gcc -o hello hello.c

bash-3.2$ time ./hello
Hello, world!

real    0m4.006s
user    0m0.001s
sys 0m0.001s

bash-3.2$ time ./hello
Hello, world!

real    0m0.004s
user    0m0.001s
sys 0m0.001s

bash-3.2$ printf '%s\n' 'package main' 'import "fmt"' 'func main() {' 'fmt.Println("test")' '}' > test.go && go build -o test ./test.go

bash-3.2$ time ./test
test

real    0m4.018s
user    0m0.001s
sys 0m0.003s

bash-3.2$ time ./test
test

real    0m0.005s
user    0m0.001s
sys 0m0.002s

答案 1 :(得分:3)

从10.15开始,每次执行新脚本时,macOS可能实际上正在与Apple通讯。我在recent changelog for TextMate中找到了它:

已修复:在macOS 10.15上重新执行(捆绑)命令时出现延迟。 从macOS 10.15开始,每次新的Apple都会“打电话回家” 脚本/二进制文件已执行,这可能会导致延迟超过 第二,取决于互联网的连接/位置。结果似乎 要按索引节点缓存,以前的TextMate将使用临时文件 在执行脚本或shell命令时(为它们提供一个新的inode 每次运行),它现在会重新使用这些文件以避免重复出现的延迟 处决。