我正在实现基于libssh(npm install ssh)
的SFTP Nodejs服务器脚本var config = require('config');
var fs = require('fs');
var path = require('path');
var libssh = require('ssh');
var server;
var options = {
host: 'localhost',
port: '3022',
// Get the common name of ssh_keys
host_key: config.get('logshipper.sftp.host_key'),
// Root path of SFTP folder on the machine
root: path.join(__dirname, config.get('logshipper.sftp.root')),
test_username: 'correct_username',
test_password: 'correct_password'
};
server = libssh.createServer({
hostRsaKeyFile: __dirname + '/ssh_keys/' + 'rsa_' + options.host_key,
hostDsaKeyFile: __dirname + '/ssh_keys/' + 'dsa_' + options.host_key
});
server.on('connection', function (session) {
session.on('auth', function (message) {
// Maybe check username/password
return message.replyAuthSuccess();
});
session.on('channel', function (channel) {
channel.on('subsystem', function (message) {
if (message.subsystem == 'sftp') {
message.replySuccess();
message.sftpAccept();
}
});
channel.on('sftp:realpath', function (message) {
console.log('server cmd sftp:realpath');
if (message.filename == '.' || (/\/$/).test(message.filename)) {
message.replyName(path.join(options.root, message.filename), {
permissions: +libssh.Stat('777').dir()
})
} else {
message.replyName(message.filename, {
permissions: +libssh.Stat('777').reg()
})
}
});
channel.on('sftp:stat', statHandle);
function statHandle(message) {
console.log('server cmd sftp:stat');
var attrs = {
permissions: +libssh.Stat(777).dir()
, uid: 101
, gid: 202
, size: 100
, atime: Date.now()
, mtime: Date.now()
};
message.replyAttr(attrs)
}
// can be handled the same way as 'stat' if you like
channel.on('sftp:lstat', statHandle);
channel.on('sftp:opendir', function (message) {
console.log('server cmd sftp:opendir');
message.replyHandle(message.filename + '/');
});
var lastmsg;
channel.on('sftpmessage', function (message) {
lastmsg = message
});
channel.on('sftp:readdir', function (message) {
console.log('server cmd sftp:readdir', message.handle);
if (lastmsg.type == 'readdir') {
return message.replyStatus('ok');
}
var readPath = message.handle;
fs.readdir(readPath, function(err, files) {
if (err) {
console.log(err);
throw err;
} else {
files = files.map(function(file) {
return {
filename: file,
longname: file,
attrs: { permissions: +libssh.Stat(644).reg() }
};
});
return message.replyNames(files);
}
});
});
channel.on('sftp:close', function (message) {
console.log('server cmd sftp:close');
message.replyStatus('ok');
})
})
});
server.listen(options.port, options.host);
console.log('Listening on port ' + options.port);
Ubuntu 14.04,nodejs 0.10.25 在sftp.root目录中,我有测试文件,我应该可以下载到,检查它是否在sftp服务器上等。
当我使用sftp(ubuntu cmd连接到我得到的服务器)时:
sftp -P 3022 localhost
Connected to localhost.
sftp> dir
Couldn't read directory: No error
test-file
sftp>
服务器输出:
/usr/bin/node sftpServer.js
Listening on port 3022
server cmd sftp:realpath
server cmd sftp:opendir
server cmd sftp:readdir /home/MyFolder/uploads/
server cmd sftp:readdir /home/MyFolder/uploads/
server cmd sftp:close
无法读取目录:无错误
但它实际上是一个测试,我需要通过lftp
使用这个服务器lftp sftp://localhost:3022
lftp localhost:~> dir
ls: ls: Access failed:
lftp localhost:~>
我正在访问失败的错误。我试图将文件夹chmod 777或标记为root组,但它没有帮助。
我希望有人会调查并帮助我找出出现此访问错误的原因,谢谢!
答案 0 :(得分:1)
最后的replyNames应该包含EOF标志,而replyStatus必须包含代码SSH_FX_EOF。否则,状态将被视为错误。 也许这段代码会这样做:
if (lastmsg.type == 'readdir') {
return message.replyStatus('eof');
}
在lftp中启用debug以查看协议消息,然后比较成功会话与不成功会话是很有用的。