猿问

为什么我的程序返回错误,指出文件不存在?

我正在编写自定义计划工具的基础知识,该工具将读取“作业”的配置文件,并将它们添加到计划中以定期运行。它现在是非常基本的,比如重构之前的概念证明和一些其他更高级的功能。


当我尝试运行此程序时,它报告找不到该脚本。脚本“test1.sh”确实存在于我尝试从中运行它的路径中,并且它具有执行权限。


我收到以下错误,但无法解释它或解决它,因为脚本确实存在于我运行它的路径中:


-> ./scheduler-example

2021/08/16 12:48:54 fork/exec /Users/me/scheduler-example/scripts/test1.sh: no such file or directory

调度程序代码:


package main


import (

    "io"

    "log"

    "os"

    "os/exec"

    "path/filepath"

    "time"


    "github.com/go-co-op/gocron"

    "gopkg.in/yaml.v3"

)


type Config struct {

    GlobalLog string `yaml:"GlobalLog"`

    Jobs      []Job  `yaml:"Jobs"`

}


type Job struct {

    Name      string `yaml:"Name"`

    Command   string `yaml:"Command"`

    Frequency string `yaml:"Frequency"`

    Tag       string `yaml:"Tag,omitempty"`

    Log       string `yaml:"Log,omitempty"`

}


const ROOT string = "/Users/me/scheduler-example"


func main() {

    // STEP1: Parse the config file

    configFile := filepath.Join(ROOT, "config", "scheduler-example.yaml")

    f, err := os.Open(configFile)

    if err != nil {

        log.Fatalln(err)

    }


    configData, err := io.ReadAll(f)

    if err != nil {

        log.Fatalln(err)

    }


    c := Config{}

    err = yaml.Unmarshal(configData, &c)

    if err != nil {

        log.Fatalln(err)

    }


    // STEP2: Validate the config

    if c.GlobalLog == "" {

        log.Fatalln("Global log not defined")

    }

    if c.Jobs == nil {

        log.Fatalln("No jobs defined")

    }

    for _, j := range c.Jobs {

        if j.Name == "" {

            log.Fatalln("Job name not defined")

        }

        if j.Command == "" {

            log.Fatalln("Job command not defined")

        }

        if j.Frequency == "" {

            log.Fatalln("Job frequency not defined")

        }

    }


人到中年有点甜
浏览 108回答 2
2回答

手掌心

根据 Go 文档包执行运行外部命令。它包装操作系统。启动过程,以便更轻松地重新映射 stdin 和标准输出、使用管道连接 I/O 以及执行其他调整。它将启动一个隔离的操作系统进程。你需要的是一个终端会话或一个直接的bash呼叫。在 Linux 中,当你称呼它时,实际上意味着 . 之所以有效,是因为终端(或WINDOWS上.bat文件的CMD)将文件逐行视为纯bash命令。因此,要运行用户定义的bash文件,我们可以使用./script.sh/bin/sh  script.sh./script.shcmd := exec.Command("/bin/sh",script)或cmd := exec.Command("bash",script)更新:如果这种方法对您有用,请阅读torek的answare以了解为什么这有效。实际上,我所说的“./script.py 蜂鸣的抨击./script.sh 是”并不是安静的。

慕尼黑5688855

以下是对OZahed答案的一个小小的技术更正,与Go语言并不真正相关,但对于了解您是否在Linux和Unix系统上编写代码很有用。在 Linux 中,当你称呼它时,实际上意味着 ../script.sh/bin/sh script.sh这并不完全正确。在类Unix系统上,当你坐在终端提示符(或者或者你设置了提示符的任何东西)时——很多人使用魔术提示器,以便他们获得他们当前的工作目录,也许还有一些Git存储库信息或其他有用的项目),你会输入一个命令::$>%$ cmd arg1 arg2例如。您正在使用的 shell —, , , , , ,等 - 负责分解输入的行并尝试运行一个或多个进程。通常,他们会将其分解为 、等。如果其中一些单词包含 shell 元字符(、等),它们将对这些元字符执行自己的特殊操作。这些可能会变得非常复杂,但它们都取决于该特定的 shell:中使用的语法与 中的语法不同,例如,在许多重要方面。/bin/sh/bin/bash/usr/local/bin/bashdashtcshfishcmdarg1*$bashtcsh无论如何,一旦这个 shell 已经过了拆分参数并准备好调用将在 Go 中使用的相同系统调用的点,则 shell 通常会调用 ,通常在使用 或 变量搜索第一个或最佳可执行文件之后(再次以 shell 相关的方式)。此系统调用:execveexec.Cmdexecve$path$PATHexecve要求提供的路径名为文件;要求使用执行权限标记命名文件;和要求命名文件包含操作系统本身认为可执行的数据。如果这三个测试中的任何一个失败,系统调用本身将失败。execve正是在这一点上,Go和外壳往往会急剧分化。如果文件存在并标记为可执行文件,但失败,则 shell 通常会执行以下一项或两项操作:exec.Cmdexecve打开并读取(可能只是文件的一部分),以尝试猜测哪个shell(如果有的话)可以运行此文件,然后对该文件运行该外壳程序或某个默认外壳程序。例如,这是导致 的最后一步。如果脚本看起来像是脚本,则 shell(即使是 ) 也应使用 。如果脚本看起来像是脚本,则 shell 应找到该程序并使用作为参数运行该程序。/bin/sh ./script.sh/bin/shtcsh/bin/sh ./scriptbashbash./script.sh了解可执行脚本的关键技巧:#!请注意,上述要求我们从操作系统级系统调用中获取错误。在任何现代Unix系统上,我们都可以通过用一条特殊的行开始我们的脚本来避免这个错误。此特殊行采用两个字符的形式,后跟可选的空格,后跟解释器程序的路径名,后跟更多可选的空格,以及一个或多个参数(具体取决于特定操作系统)。execve#!也就是说,如果我们将 shell 脚本编写为:#! /bin/sh echo this was run by /bin/sh并使其可执行,应用于此脚本的系统调用,就好像它是一个系统调用,后跟此脚本的路径名。因此,如果我们使用的路径名是 ,我们会得到运行的效果。execveexecve/bin/sh./script/bin/sh ./script该部分来自脚本,因此我们可以控制解释器的确切路径。例如,如果我们编写一个 awk 脚本,并且如果解释器位于 中,则:/bin/shawk/usr/bin/awk#! /usr/bin/awk是正确的第一行。有趣的是,这使我们能够编写一个自我删除的脚本:#! /bin/rm运行时,此脚本将自行删除。(文件的其余部分(如果有)无关紧要:该命令只是删除命名文件。使用 作为解释器生成自重命名脚本。/bin/rm/bin/mv由于某些系统和其他系统上的程序,如今的一个常见技巧是使用POSIX命令来查找解释器的二进制文件:python/usr/bin/usr/local/binenv#! /usr/bin/env python调用。该命令用于查找命令,然后调用(系统调用的 C 库包装器)或任何合适的内容。如果一个系统同时安装了 python2 和 python3,并且调用了特定的变体,则确保我们找到一个 python3 解释器,而不是一个 python2 解释器。/usr/bin/env python ./script.pyenv$PATHpythonexeclexecve/usr/local/bin/python ./script.pypython2python3#! /usr/bin/env python3如果你用适当的台词来写你的剧本,你永远不会问到导致这些答案的问题。:-)#!
随时随地看视频慕课网APP

相关分类

Go
我要回答