我有一个使用SSH.NET在Unix机器上调用shell脚本的Web服务。
如果我正常运行脚本,它可以正常工作,在Informix DB上正常工作。
只是一些背景:
我调用一个执行.4gl
的脚本(不能将此作为其商业知识)。
当我使用SSH.NET执行它时,g4l会在日志中返回以下错误:
fglgo:加载共享库时出错:libiffgisql.so:无法打开共享对象文件:没有这样的文件或目录
file_load结束:2017-09-21 15:37:01
执行SSH.NET脚本的C#代码
sshclients = new SshClient(p, 22, username, password);
sshclients.Connect();
sshclients.KeepAliveInterval = new TimeSpan(0, 0, 1);
sshclients.RunCommand("sh " + Script_dir);
我添加了KeepAliveInterval
,看看是否有帮助。
我的问题是我从Unix / 4gl得到的错误。
为什么会发生这种情况以及我可以让谁能正确执行脚本?
答案 0 :(得分:0)
SshClient.RunCommand
内部使用SSH“exec”频道。默认情况下,它(正确地)不会为会话分配伪终端(PTY)。因此,可能(可能)采购了一组不同的启动脚本。和/或脚本中的不同分支基于public class StringDecomposer {
public String process(String input) {
StringBuilder result = new StringBuilder();
decompres(input, 0, result);
return result.toString();
}
private int decompres(String input, int ofset, StringBuilder result) {
StringBuilder rpt = new StringBuilder();
StringBuilder current = new StringBuilder();
while(ofset < input.length()) {
if(input.charAt(ofset) == '[') {
ofset = decompres(input, ofset+1, current);
repeat(rpt, current);
result.append(current);
rpt.delete(0, rpt.length());
current.delete(0, current.length());
}
else if(input.charAt(ofset) == ']') {
break;
}
else if(input.charAt(ofset) > 47 &&
input.charAt(ofset) < 58) {
rpt.append(input.charAt(ofset));
}
else {
current.append(input.charAt(ofset));
}
ofset++;
}
result.append(current);
return ofset;
}
private void repeat(StringBuilder rpt, StringBuilder input) {
if(rpt.length() > 0) {
StringBuilder current = new StringBuilder(input);
int times = Integer.parseInt(rpt.toString());
for(int i = 1; i < times; i++) {
input.append(current);
}
}
}
}
环境变量的缺失/存在而被采用。因此环境可能与交互式会话不同,您可以使用SSH客户端。
因此,在您的情况下,TERM
可能设置不同;因此无法找到共享对象。
要验证这是根本原因,请在SSH客户端中禁用伪终端分配。例如,在PuTTY中,它是 Connection&gt; SSH&gt; TTY&gt;不要分配伪终端。然后,转到 Connection&gt; SSH&gt;远程命令并输入您的PATH
命令。检查会话&gt;关闭退出窗口&gt;从不并打开会话。你应该得到相同的“没有这样的文件或目录”错误。
如何按优先顺序解决此问题:
修复脚本不依赖于特定环境。
修复启动脚本,为交互式和非交互式会话设置g4l
相同。
如果命令本身依赖于特定的环境设置而无法修复启动脚本,则可以在命令本身中更改环境。该语法取决于远程系统和/或shell。在常见的* nix系统中,这有效:
PATH
另一种(不推荐)方法是强制“exec”频道的伪终端分配。
虽然SSH.NET不支持此功能。您必须在sshclients.RunCommand("PATH=\"$PATH;/path/to/g4l\" && sh ...");
实施中修改其代码问题SendPseudoTerminalRequest
请求(我没有对此进行测试)。
您还可以尝试使用.CreateShell
method使用“shell”频道。对于它,SSH.NET确实支持伪终端分配。
尽管使用伪终端自动执行命令会带来令人讨厌的副作用。例如,请参阅Is there a simple way to get rid of junk values that come when you SSH using Python's Paramiko library and fetch output from CLI of a remote machine?
有关类似问题,请参阅
答案 1 :(得分:0)
Informix-4gl开发人员在转换到FourJs Genero并使用其Web服务功能时遇到了类似的问题。我将向他们提出的问题是“谁拥有Genero Application Server已启动的fglgo / fglrun进程,它在哪里运行,以及它的环境是什么”。如果需要,我将用一个简单的程序来说明,它可以像......一样......
MAIN
RUN "env > /tmp/myname.txt"
RUN "who >> /tmp/myname.txt"
RUN "pwd >> /tmp/myname.txt"
END MAIN
...并说明与程序从命令行运行时的比较。通常情况下,在早期的配置答案中,以便在执行4gl程序之前正确设置环境。