inets httpd cgi脚本:为什么我收到“没有这样的文件或目录”错误?

时间:2018-02-27 11:04:38

标签: erlang inets

当我尝试从inets httpd服务器请求cgi脚本时,我收到此错误:

sh: /Users/7stud/erlang_programs/inets_proj/cgi-bin/cgi-bin/1.pl: 
No such file or directory

我注意到路径的cgi-bin组件加倍。我的cgi脚本实际上位于:

/Users/7stud/erlang_programs/inets_proj/cgi-bin/1.pl

这是我的httpd服务器proplist_file:

[
  {modules, [
        mod_alias,
        mod_cgi
  ]},
  { bind_address, "localhost"}, 
  {port,0},
  {server_name,"httpd_test"},
  {server_root,"."},
  {document_root,"./htdocs"},
  {script_alias, {"/cgi-bin/", "./cgi-bin/"} }
].

根据httpd docs

  

CGI属性 - 需要mod_cgi

     

{script_alias,{Alias,RealName}}
  Alias = string()和RealName =   串()。与属性别名具有相同的行为,但它们除外   还将目标目录标记为包含CGI脚本。带有的网址   以Alias开头的路径映射到以。开头的脚本   RealName,例如:

{script_alias, {"/cgi-bin/", "/web/cgi-bin/"}}
     

访问http://your.server.org/cgi-bin/foo会导致服务器进入   运行脚本/web/cgi-bin/foo

  

{server_root,path()}
  定义服务器的主目录,其中   可以存储日志文件等。 其他指定的相对路径   属性引用此目录。

更多信息:

5> httpd:info(S).
[{mime_types,[{"htm","text/html"},{"html","text/html"}]},
 {server_name,"httpd_test"},
 {script_alias,{"/cgi-bin/","./cgi-bin/"}},
 {bind_address,{127,0,0,1}},
 {modules,[mod_actions,mod_alias,mod_cgi,mod_get,mod_head,
           mod_log]},
 {server_root,"."},
 {port,59641},
 {document_root,"./htdocs"}]

6> pwd().
/Users/7stud/erlang_programs/inets_proj
ok

7> ls().
cgi-bin         cl.beam         cl.erl          htdocs          
s.beam          s.erl           server.conf     
ok

为什么我的请求网址中有一个加倍的cgi-bin组件?

1 个答案:

答案 0 :(得分:0)

如果我使用2018 02 27 13:17:09#+00#ERROR#org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/]##anonymous#fs-watcher#na#afc186d33#firstapp#web##na#na#na#na#Exception sending context initialized event to listener instance of class com.sap.cloud.sdk.frameworks.hystrix.ScpNeoHystrixBootstrapListenerjava.lang.IllegalStateException: Another strategy was already registered. at com.netflix.hystrix.strategy.HystrixPlugins.registerConcurrencyStrategy(HystrixPlugins.java:190) at com.sap.cloud.sdk.frameworks.hystrix.ScpNeoHystrixBootstrapListener.bootstrap(ScpNeoHystrixBootstrapListener.java:43) at com.sap.cloud.sdk.frameworks.hystrix.ScpNeoHystrixBootstrapListener.contextInitialized(ScpNeoHystrixBootstrapListener.java:74) at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:5110) at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5633) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145) at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:1015) at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:991) at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:652) at org.eclipse.gemini.web.tomcat.internal.TomcatServletContainer.startWebApplication(TomcatServletContainer.java:125) at org.eclipse.gemini.web.internal.StandardWebApplication.start(StandardWebApplication.java:109) at org.eclipse.gemini.web.extender.WebContainerBundleCustomizer.addingBundle(WebContainerBundleCustomizer.java:49) at org.osgi.util.tracker.BundleTracker$Tracked.customizerAdding(BundleTracker.java:467) at org.osgi.util.tracker.BundleTracker$Tracked.customizerAdding(BundleTracker.java:1) at org.osgi.util.tracker.AbstractTracked.trackAdding(AbstractTracked.java:256) at org.osgi.util.tracker.AbstractTracked.track(AbstractTracked.java:229) at org.osgi.util.tracker.BundleTracker$Tracked.bundleChanged(BundleTracker.java:443) at org.eclipse.osgi.framework.internal.core.BundleContextImpl.dispatchEvent(BundleContextImpl.java:847) at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:230) at org.eclipse.osgi.framework.eventmgr.ListenerQueue.dispatchEventSynchronous(ListenerQueue.java:148) at org.eclipse.osgi.framework.internal.core.Framework.publishBundleEventPrivileged(Framework.java:1568) at org.eclipse.osgi.framework.internal.core.Framework.publishBundleEvent(Framework.java:1504) at org.eclipse.osgi.framework.internal.core.Framework.publishBundleEvent(Framework.java:1499) at org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(BundleHost.java:391) at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(AbstractBundle.java:300) at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(AbstractBundle.java:292) at org.eclipse.virgo.web.war.deployer.WARDeployer.start(WARDeployer.java:780) at org.eclipse.virgo.nano.deployer.internal.StandardApplicationDeployer.startDeployables(StandardApplicationDeployer.java:325) at org.eclipse.virgo.nano.deployer.internal.StandardApplicationDeployer.bulkDeploy(StandardApplicationDeployer.java:116) at org.eclipse.virgo.nano.deployer.hot.HotDeploymentFileSystemListener.bulkDeployIfNotDeployed(HotDeployerFileSystemListener.java:143) at org.eclipse.virgo.nano.deployer.hot.HotDeploymentFileSystemListener.onInitialEvent(HotDeployerFileSystemListener.java:105) at org.eclipse.virgo.util.io.FileSystemChecker.notifyListenersOnInitialEvent(FileSystemChecker.java:207) at org.eclipse.virgo.util.io.FileSystemChecker.handleInitialFiles(FileSystemChecker.java:177) at org.eclipse.virgo.util.io.FileSystemChecker.check(FileSystemChecker.java:261) at org.eclipse.virgo.nano.deployer.hot.WatchTask.run(WatchTask.java:49) at java.lang.Thread.run(Thread.java:807) 选项中服务器的cgi-bin目录的完整路径,那么我可以成功请求cgi脚本。我无法获得相对的工作路径。这是对我有用的httpd服务器配置:

server.conf中:

script_alias

目录结构:

[
  {modules, [
    mod_alias,
    mod_actions,
    mod_cgi,
    mod_get
  ]},
  {bind_address, "localhost"}, 
  {port,0},
  {server_name,"httpd_test"},
  {server_root,"/Users/7stud/erlang_programs/inets_proj"},
  {document_root,"./htdocs"},
  {script_alias, {"/cgi-bin/", "/Users/7stud/erlang_programs/inets_proj/cgi-bin/"} }
].

s.erl:

$ tree inets_proj
inets_proj
├── cgi-bin
│   └── 1.pl
├── cl.beam
├── cl.erl
├── htdocs
│   └── file1.txt
├── s.beam
├── s.erl
└── server.conf

cgi script 1.pl(确保该文件具有可执行权限!):

-module(s).
-compile(export_all).

ensure_inets_start() ->
    case inets:start() of
        ok -> ok;
        {error,{already_started,inets}} -> ok
    end.

%After start(), need to lookup the port with:
%      3> httpd:info(Server)

start() ->
    ok = s:ensure_inets_start(),

    {ok, Server} = inets:start(httpd, 
        [{proplist_file, "./server.conf"}]
    ),
    Server.


stop(Server) ->
    ok = inets:stop(httpd, Server).

FILE1.TXT:

#!/usr/bin/env perl

use strict;
use warnings;
use 5.020;
use autodie;
use Data::Dumper;

print "Content-type: text/html\n\n";
print "Hello, Perl.\n";

在shell中:

Hello, world!

在终端窗口中:

$ erl
Erlang/OTP 19 [erts-8.2] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false]

Eshell V8.2  (abort with ^G)

1> c(s).
{ok,s}

2> S = s:start().
<0.79.0>

3> httpd:info(S).
[{mime_types,[{"htm","text/html"},{"html","text/html"}]},
 {server_name,"httpd_test"},
 {script_alias,{"/cgi-bin/",
                "/Users/7stud/erlang_programs/inets_proj/cgi-bin/"}},
 {bind_address,{127,0,0,1}},
 {modules,[mod_alias,mod_actions,mod_cgi,mod_get]},
 {server_root,"/Users/7stud/erlang_programs/inets_proj"},
 {port,54344},
 {document_root,"./htdocs"}]

4> 

尽管文档说明必须使用~$ curl -v "http://localhost:54344/cgi-bin/1.pl" * Trying 127.0.0.1... * TCP_NODELAY set * Connected to localhost (127.0.0.1) port 54344 (#0) > GET /cgi-bin/1.pl HTTP/1.1 > Host: localhost:54344 > User-Agent: curl/7.58.0 > Accept: */* > < HTTP/1.1 200 OK < Date: Wed, 28 Feb 2018 03:18:05 GMT < Server: inets/6.3.4 < Transfer-Encoding: chunked < Content-Type: text/html < Hello, Perl. * Connection #0 to host localhost left intact ~$ curl -v "http://localhost:54344/file1.txt" * Trying 127.0.0.1... * TCP_NODELAY set * Connected to localhost (127.0.0.1) port 54344 (#0) > GET /file1.txt HTTP/1.1 > Host: localhost:54344 > User-Agent: curl/7.58.0 > Accept: */* > < HTTP/1.1 200 OK < Date: Wed, 28 Feb 2018 03:18:56 GMT < Server: inets/6.3.4 < Content-Type: text/plain < Etag: nCZT0114 < Content-Length: 14 < Last-Modified: Mon, 26 Feb 2018 02:51:52 GMT < Hello, world! * Connection #0 to host localhost left intact $ 的主机语法作为输出 - 而不是您为httpd:info()指定的内容 - 我可以在请求中使用{bind_address, "localhost"}

以下是使用localhost向httpd服务器发送cgi帖子请求的示例:

httpc

httpd的cgi实现似乎有问题,因为我无法发出包含json数据的cgi post请求。 cgi脚本必须读取请求的主体以获取原始字符串,并且我已尝试使用perl cgi脚本-module(cl). -compile(export_all). ensure_inets_start() -> case inets:start() of ok -> ok; {error,{already_started,inets}} -> ok end. start() -> ensure_inets_start(). %% Need "http://" at start of url: %% %% cl:myget("http://localhost:62049/file1.txt") %% %% Need to look up port with httpd:info(Server) myget(Url) -> {ok, ReqRef} = httpc:request(get, {Url, []}, [], [{sync, false}]), receive {http, {ReqRef, Result}} -> Result after 2000 -> my_error end. stop() -> inets:stop(). url(Port) -> "http://localhost:" ++ integer_to_list(Port) ++ "/cgi-bin/1.pl". mypost(Port) -> Url = url(Port), Headers = [], ContentType = "application/x-www-form-urlencoded", Body = "a=1&b=2", Request = {Url, Headers, ContentType, Body}, HttpOptions = [], Options = [{sync, false}], {ok, ReqRef} = httpc:request(post, Request, HttpOptions, Options), receive {http, {ReqRef, Result}} -> Result; Other -> Other after 1000 -> my_error end. 和python cgi脚本$str = $q->param('POSTDATA');来执行此操作。我无法从httpd服务器获取请求的正文。