在GitHub Actions中运行Go脚本时出现Permission Denied错误求助
问题:GitHub Actions中Go测试因硬件命令不可用失败
我有一个Go项目,用于提供Debian系列发行版的CPU温度、时钟频率等系统信息接口。本地构建和测试都正常,但在GitHub Actions中执行测试时失败,Shell脚本返回错误码1。
相关Go函数
//GetTemp returns the current CPU temperature in C func GetTemp() (temp float64, err error) { cmd := exec.Command("bash", "-c", "/usr/bin/vcgencmd measure_temp | egrep -o '[0-9]*\\.[0-9]*'") out, err := cmd.Output() if err != nil { return -1, err } res := strings.TrimSuffix(string(out), "\n") temp, _ = strconv.ParseFloat(res, 64) return temp, nil }
对应测试函数
func TestTempRange(t *testing.T) { expectedMin, expectedMax := 0.0, 120.0 actual, err := GetTemp() if err != nil { t.Fatalf("Error retrieving cpu temp\nError: %v", err) } if actual < expectedMin || actual > expectedMax { t.Fatalf("return temp outside of acceptable range.\nExpected temp within range [%v, %v]\nRecieved %v", expectedMin, expectedMax, actual) } }
GitHub Actions构建配置
jobs: build: runs-on: ubuntu-latest strategy: matrix: go-version: [ '1.14', '1.15', '1.16.x' ] steps: - uses: actions/checkout@v3 - name: Set up Go uses: actions/setup-go@v3 with: go-version: ${{ matrix.go-version }} - name: Install dependencies run: go get . - name: Build run: go build -v ./... - name: Test with Go run: go test -json > TestResults-${{ matrix.go-version }}.json - name: Upload Go test results uses: actions/upload-artifact@v3 with: name: Go-results-${{ matrix.go-version }} path: TestResults-${{ matrix.go-version }}.json
GitHub Actions错误输出
Run go test `go list ./... | grep -v examples` -coverprofile=coverage.txt -covermode=atomic ? github.com/rafaelzasas/rpiSystemMonitor [no test files] --- FAIL: TestTempRange (0.02s) cpu_test.go:9: Error retrieving cpu temp Error: exit status 1 --- FAIL: TestFreqRange (0.03s) cpu_test.go:22: Error retrieving cpu freq Error: exit status 1 FAIL coverage: 57.1% of statements FAIL github.com/rafaelzasas/rpiSystemMonitor/cpu 0.047s ok github.com/rafaelzasas/rpiSystemMonitor/mem 0.044s coverage: 42.9% of statements FAIL Error: Process completed with exit code 1.
问题原因与解决办法
核心原因
GitHub Actions使用的ubuntu-latest是x86架构的标准虚拟机,而vcgencmd是树莓派(ARM架构)专属的硬件查询工具,在普通Ubuntu环境中不存在,这是测试失败的根本原因。
可行解决方案
1. 跳过硬件相关测试
在测试命令中排除包含硬件调用的包,修改GitHub Actions的测试步骤:
go test $(go list ./... | grep -v cpu) -json > TestResults-${{ matrix.go-version }}.json
或者在测试代码中添加环境判断,自动跳过非树莓派环境的测试:
func TestTempRange(t *testing.T) { // 检查vcgencmd是否存在,不存在则跳过测试 if _, err := exec.LookPath("vcgencmd"); err != nil { t.Skip("vcgencmd not found, skipping hardware-dependent test") } // 原有测试逻辑 expectedMin, expectedMax := 0.0, 120.0 actual, err := GetTemp() if err != nil { t.Fatalf("Error retrieving cpu temp\nError: %v", err) } if actual < expectedMin || actual > expectedMax { t.Fatalf("return temp outside of acceptable range.\nExpected temp within range [%v, %v]\nRecieved %v", expectedMin, expectedMax, actual) } }
2. Mock硬件调用逻辑
重构代码,将硬件查询逻辑抽象为接口,测试时用Mock实现替代真实调用:
- 定义接口:
type SystemInfoGetter interface { GetTemp() (float64, error) } - 真实环境实现:
type RealSystemInfo struct{} func (r RealSystemInfo) GetTemp() (float64, error) { cmd := exec.Command("bash", "-c", "/usr/bin/vcgencmd measure_temp | egrep -o '[0-9]*\\.[0-9]*'") out, err := cmd.Output() if err != nil { return -1, err } res := strings.TrimSuffix(string(out), "\n") temp, _ := strconv.ParseFloat(res, 64) return temp, nil } - 测试用Mock实现:
type MockSystemInfo struct{} func (m MockSystemInfo) GetTemp() (float64, error) { return 50.0, nil // 返回合法测试值 } - 修改测试函数使用Mock:
func TestTempRange(t *testing.T) { getter := MockSystemInfo{} expectedMin, expectedMax := 0.0, 120.0 actual, err := getter.GetTemp() if err != nil { t.Fatalf("Error retrieving cpu temp\nError: %v", err) } if actual < expectedMin || actual > expectedMax { t.Fatalf("return temp outside of acceptable range.\nExpected temp within range [%v, %v]\nRecieved %v", expectedMin, expectedMax, actual) } }
3. 使用ARM架构运行环境
在GitHub Actions中配置ARM架构的Runner或用QEMU模拟树莓派环境,这种方式配置复杂且运行速度较慢,仅适合必须测试真实硬件逻辑的场景。
内容的提问来源于stack exchange,提问作者Rafael Zasas
相关产品推荐
相关产品推荐

