vro*_*911 1 bash haskell haskell-stack
我有一个非常简单的haskell项目,只有可执行文件my-exec.它所做的就是打印"Hello,world!" 控制台.
我想创建脚本文件bin/setup.sh,它将运行我的可执行文件,也做一些echo
#!/usr/bin/env stack
-- stack exec bash
echo Echo printing
my-exec
Run Code Online (Sandbox Code Playgroud)
当我跑它时,我得到了
$ ./bin/setup.sh
./bin/setup.sh: line 2: --: command not found
Echo printing
Hello, world!
Run Code Online (Sandbox Code Playgroud)
我不明白这个文件的问题是什么,为什么它说--: command not found但仍然按预期工作.
我知道在这个简单的例子中我可以用更容易的形式编写它,但在我的实际情况中,我必须做10个非平凡的exec调用,并且不想stack exec多次重复.
那么我该怎么做才能摆脱这个错误呢?
这是问题所在.第一行:
#!/usr/bin/env stack
Run Code Online (Sandbox Code Playgroud)
由您的操作系统(例如,Linux内核)解释为指示应使用等效的shell命令调用脚本:
$ /usr/bin/env stack setup.sh
Run Code Online (Sandbox Code Playgroud)
或者,因为env只是在那里搜索路径stack,相当于:
$ stack setup.sh
Run Code Online (Sandbox Code Playgroud)
如果您手动运行,您将收到相同的错误.那是因为,当stack以这种方式调用时,它会读取指定的文件,搜索表单的一行:
-- stack blah blah whatever blah blah
Run Code Online (Sandbox Code Playgroud)
在第一#!行之后.通常,这一行看起来像:
-- stack --resolver lts-10.0 script
Run Code Online (Sandbox Code Playgroud)
告诉堆栈运行脚本,就像运行shell命令一样:
$ stack --resolver lts-10.0 script hello.sh
Run Code Online (Sandbox Code Playgroud)
它解释hello.sh为Haskell程序,而不是shell脚本,但使用lts-10.0解析器运行它,一切都很好.
但是,您已经告诉stack要使用该命令stack exec bash,因此stack调用您的脚本相当于:
$ stack exec bash hello.sh
Run Code Online (Sandbox Code Playgroud)
这与运行基本相同:
$ bash hello.sh
Run Code Online (Sandbox Code Playgroud)
设置stack路径后等.
最后,shell bash正在运行您的脚本.Bash忽略第一行,因为它以#表示shell注释的字符开头.但是当Bash尝试解释第二行时,就像在shell提示符下输入以下命令一样:
$ -- stack exec bash
Run Code Online (Sandbox Code Playgroud)
Bash查找名为--使用参数运行的程序stack exec bash,并且您收到错误消息.尽管如此,脚本仍在运行,因此echo和my-exec行按预期运行.
哇.
这是一种可能适合您的方式.您可以使用:
#!/bin/bash
exec stack exec bash <<EOF
echo Echo printing
./hello
EOF
Run Code Online (Sandbox Code Playgroud)
这个shell脚本将stack exec bash使用所谓的"here doc"调用,基本上将所有内容传递给EOF作为脚本文件stack exec bash运行.