判断端口是否可以(未被占用)
(port int)
| 52 | |
| 53 | // 判断端口是否可以(未被占用) |
| 54 | func IsPortAvailable(port int) (result bool, err error) { |
| 55 | //1. 使用golang进行验证 |
| 56 | //1.1. localhost判断 |
| 57 | l, err := net.Listen("tcp", "localhost:"+strconv.Itoa(port)) |
| 58 | if err != nil { |
| 59 | SmartIDELog.Debug(fmt.Sprintf("localhost:%v used, "+err.Error(), port)) |
| 60 | return false, err |
| 61 | } |
| 62 | defer l.Close() |
| 63 | //1.2. 通用判断 |
| 64 | if runtime.GOOS != "linux" { |
| 65 | l2, err := net.Listen("tcp", ":"+strconv.Itoa(port)) // 没有ip的形式,在linux中运行异常 |
| 66 | if err != nil { |
| 67 | SmartIDELog.Debug(fmt.Sprintf(":%v used, "+err.Error(), port)) |
| 68 | return false, err |
| 69 | } |
| 70 | defer l2.Close() |
| 71 | l2.Close() |
| 72 | } |
| 73 | l.Close() |
| 74 | |
| 75 | //2. 使用命令行工具进行验证 |
| 76 | //2.1. command |
| 77 | command := "" |
| 78 | switch runtime.GOOS { |
| 79 | case "linux": |
| 80 | command = fmt.Sprintf("sudo lsof -nP -iTCP:%v -t -sTCP:LISTEN", port) |
| 81 | case "windows": |
| 82 | command = fmt.Sprintf("netstat -aon|findstr \":%d\"", port) |
| 83 | case "darwin": |
| 84 | command = fmt.Sprintf("lsof -i tcp:%d -t", port) // 输出的是进程id |
| 85 | default: |
| 86 | err = errors.New("unsupported platform") |
| 87 | return |
| 88 | } |
| 89 | output, err := EXEC.CombinedOutput(command, "") |
| 90 | if _, ok := err.(*exec.ExitError); ok { // 排除exitError |
| 91 | err = nil |
| 92 | } |
| 93 | //2.2. 根据输出判断端口是否占用 |
| 94 | if runtime.GOOS != "windows" { |
| 95 | result = strings.TrimSpace(output) == "" // 如果没有返回pid,代表可用(没有被占用) |
| 96 | } else { |
| 97 | if !strings.Contains(string(output), string(rune(port))) { |
| 98 | result = true // 端口未被占用 |
| 99 | } else { |
| 100 | SmartIDELog.Debug(fmt.Sprintf("%v used,"+string(output), port)) |
| 101 | } |
| 102 | } |
| 103 | |
| 104 | return |
| 105 | } |
| 106 | |
| 107 | // 检查当前端口是否被占用,并返回一个可用端口 |
| 108 | func CheckAndGetAvailableLocalPort(checkPort int, step int) (usablePort int, err error) { |
no test coverage detected