【问题标题】:CoffeeScript in a shell script -- run by Apache (as CGI)Shell 脚本中的 CoffeeScript——由 Apache 运行(作为 CGI)
【发布时间】:2016-10-25 18:53:34
【问题描述】:

按照here 的建议,我可以在 JavaScript 中获得一个 shell 脚本,它在 node.js 下运行并打印一些 hello world html:

test.cgi
-------
#!/usr/local/bin/node

console.log("Content-Type: text/html; charset=utf-8\n");
console.log("<html><body><h1>hello node.js world</h1></body></html>");
-------

并运行它:

$ ./test.cgi
Content-Type: text/html; charset=utf-8

<html><body><h1>hello node.js world</h1></body></html>

它在 Apache 中也能按预期工作,并在浏览器中显示预期的 HTML。

现在转到 CoffeeScript(注意这里可爱的三引号文档,Python 风格):

ctest.cgi
-------
#!/usr/bin/env coffee

console.log("Content-Type: text/html; charset=utf-8\n");
console.log('''<html><body><h1>hello CoffeeScript world
</h1></body></html>''');
-------

这在本地运行时有效:

$ ./ctest.cgi
Content-Type: text/html; charset=utf-8

<html><body><h1>hello CoffeeScript world
</h1></body></html>

但不是在 Apache 中:

Internal Server Error

为什么这不起作用?

【问题讨论】:

    标签: apache node.js cgi coffeescript env


    【解决方案1】:

    我试图通过从 CoffeeScript 逆向工程 command.js 并通过以下 JavaScript node.js shell 脚本直接运行我的咖啡脚本(上面的 ctest.cgi)来解决这个问题:

    drip
    -------
    #!/usr/local/bin/node
    
    var fs = require('fs');
    var cs = require('/usr/local/lib/coffee-script/lib/coffee-script');
    var args = process.argv;
    var fname = args[2];
    if (fname)
    {
        fs.readFile(fname, function (err, data) {
          if (err) throw err;
          var text = data.toString(); //console.log(data.toString());
          cs.run(text, {'filename':fname, 'bare':undefined});
        });
    }
    -------
    

    我把它放在 /usr/local/bin/drip 中,现在我可以运行 ctest.cgi,只需对顶行稍作改动:

    #!/usr/bin/env /usr/local/bin/drip
    

    现在我可以破解 CoffeeScript CGI 脚本并在浏览器中点击重新加载,而不必在更改 .coffee 文件时手动调用 CoffeeScript 编译器。

    【讨论】:

    • 如果您要在性能关键的环境中使用 CoffeeScript for CGI,这可能是正确的方向,因为如果您每次都使用 coffee 运行脚本,则会产生开销每次都编译 CoffeeScript。相反,您可能希望扩展上述脚本,以便在不存在此类文件或 .coffee 文件上的时间戳更新时将其编译为 .js 文件,然后运行 ​​.js 文件。
    • @Trevor:编译是一个非常棒的主意。另外,我刚刚看到我可以在 catch 块中打印一些基本的 http 标头,以便在浏览器中打印异常跟踪,而不是在脚本中出现语法错误时跟踪 /var/log/apache2/error_log。顺便说一句,我的方法并不是对性能很重要,而是我希望有机会尝试使用 CoffeeScript 作为我的 Python CGI 脚本的替代品,作为用在浏览器中运行的脱机 JS 完全替换 Python 计划的一部分——因为“ CoffeeScript IS JavaScript”——和 Python 一样漂亮。
    • 实际上如果我添加编译方法,它可能有助于解决另一个问题,即:允许coffee CGI脚本在同一文件夹中“要求”其他.coffee文件(我会添加相同的逻辑到如果 .coffee 时间戳不匹配,则重新编译所需的 .js)。如果我得到一些有用的东西,我会把它发布到 github。
    【解决方案2】:

    您可能已经想到了这一点,但是:您是否尝试过替换

    #!/usr/bin/env coffee
    

    绝对引用coffee 所在的位置? env 依赖于 PATH 环境变量,当您运行 ./ctest.cgi 时,您的 PATH 不一定与 Apache 的相同。

    【讨论】:

    • 我试过了,但是 /usr/local/bin/coffee 脚本使用了为我的用户定义但不在用户上下文中的相同类型的“/usr/bin/env node”位Apache 运行。现在我只是尝试将咖啡的第一行更改为对节点的绝对引用,但是咖啡脚本中的路径黑客无法链接到 /usr/local/lib/coffee-script/lib 中的正确位置,因此对咖啡进行了更多修改脚本是必需的,这是我上面滴水脚本的精髓。
    • 啊,我明白了。好吧,我不是 Apache 专家,但是您是否尝试过使用 mod_env 设置 PATH 变量,使其同时指向 coffeenode
    【解决方案3】:

    这是我的设置,任何有兴趣的人。

    这对性能非常不利!

    ~/coffee
    ------
    #!/usr/bin/perl 
    
    # this is coffee runner!
    
    print ` PATH="\$PATH:~/www/cgi-bin/bin" ; ~/www/cgi-bin/bin/node_modules/coffee-script/bin/coffee $ARGV[0] 2>&1 `;
    ------
    

    我没有必要改变我的服务器环境,所以我要在这里添加我的节点路径。但是,我可以在 .htaccess 中设置一个处理程序:

    ~/dir/.htaccess
    ------
    AddHandler cgi-script .litcoffee
    DirectoryIndex cv.litcoffee
    ------
    

    这意味着我可以像 CGI 一样运行 literate 并为浏览器提供咖啡 :-) 效率非常低,但反正没有多少人访问我的网站。

    然后我的每个脚本看起来都像这样......

    ~/web/ascript.litcoffee
    ------
    #!/usr/bin/perl /home/jimi/coffee
    
    This is literate coffeescript!
    
        module.paths.push "/home/jimi/www/cgi-bin/bin/node_modules"
        require "coffee-script"
    
    This is a wee module I wrote for spewing tags, with content and attributes
    
        global[k.toUpperCase()] = v for k,v of require './html.litcoffee'
    
    It also provides a header function, but I'm going to move that to a CGI module when I get around to it.
    
        console.log CGI_HEADER()
    
    Now we can put something to the browser.
    
        console.log HTML [
            HEAD [
                META {charset:"utf-8"}
                SCRIPT [],
                    src : "https://raw.github.com/jashkenas/coffee-script/master/extras/coffee-script.js"
                SCRIPT [],
                    src : "runsonclient.coffee"
                    type    : "text/coffeescript"
                LINK
                    rel : "stylesheet"
                    href    : "mystyles.css"
                TITLE "A page title"
            ]
            BODY [
                H1 "a page title"
                INPUT 
                    id     : "myinput"
                    type   : "text"
                SVG
                    id     : "mysvg"
                    width  : "80%"
                    height : "20"
                DIV
                    id     : "mydiv"
            ]
        ]
    ------
    

    我知道它不漂亮,但它确实有效。并且从脚本运行(尽管它不必是 perl!)允许 2>&1 所以我所有的错误都会出现在屏幕上,除非我的标题没有被打印出来......但是 Jared Updike 已经用 try 块解决了这个问题.

    【讨论】:

    • 我试图编辑和更新这个,但它被拒绝了......想分享脚本的更新:
    【解决方案4】:

    我不知道咖啡为什么会失败,但一个可能(并且非常简单)的解决方案是将您的代码放在一个单独的文件(test.coffee)中并执行要求:

    #!/usr/local/bin/node
    
    require('coffee-script')
    require('./test')
    

    (在需要咖啡脚本后自动注册扩展)

    【讨论】:

    • 我对此进行了测试(将其粘贴到 rtest.cgi 中),它在我的用户下的命令行中运行良好,但在 Apache 下作为 CGI 脚本加载时失败(其他 .cgi 脚本在同一文件夹工作正常)。错误日志显示异常:找不到模块“咖啡脚本”。总的来说,如果我们可以通过 env 变量以外的其他方式或通过正确的 env var 让节点了解咖啡脚本,这似乎是正确/最佳的方法。
    • 模块安装到用户的路径(~/.node_modules)。尝试设置 NODE_PATH 环境变量。
    【解决方案5】:

    我试图更新我的答案,但被拒绝了,有人建议将其添加为单独的答案...

    我刚刚将它更新为一个带有 compile if newer 功能的 shell 脚本:

    #!/bin/sh
    CS=$1        # the coffeescript to be run
    # the following works because (my) apache runs in the script's directory and passes just the filename (no path)
    # if would be safer to test that this is the case, or make sure the dot is added to the filename part
    JS=.$CS.cjs  # the compiled javascript
    CE=.$CS.cerr # compiler errors
    PATH="$PATH:/home/jimi/www/cgi-bin/bin:/home/jimi/www/cgi-bin/bin/node_modules/coffee-script/bin"
    if [ ! -f $JS ] || [ $CS -nt $JS ] ; then
        coffee -c -p $1>$JS 2>$CE
    fi
    node $JS 2>&1   # runtime errors to browser
    

    【讨论】:

      猜你喜欢
      • 2013-03-30
      • 2011-08-27
      • 1970-01-01
      • 1970-01-01
      • 2014-01-02
      • 1970-01-01
      • 2012-04-05
      • 2015-05-27
      • 2017-03-25
      相关资源
      最近更新 更多