In all honesty this is a hacky way of building an FTP service.  Ideally 
you'd build a TCP server and properly handle FTP commands but with a 
cleaner interface for your application.  If you use this .spawn way you 
need to manage state (which commands were issued, did they complete 
successfully or failed, what data was sent, etc.) and passing the complete 
data back to the application.

It seems as tho node-sftp is fairly complete but I don't know how well it 
works.  I think it's worth giving a try especially if you have simple use 
cases.

Good luck
Roy

On Tuesday, July 31, 2012 4:24:08 AM UTC-4, carlton wrote:
>
> Thanks for the responses, after reading those and doing some additional 
> reading on the tube I understand the difference between callbacks and 
> eventEmitters better.
>
> I'll go away and have a think about how to handle the data event, I'll 
> also try and kick start the node-sftp library that I was using, I think it 
> was fairly close to working properly.
>
> So am I right in thinking that I need to parse the stdout data to figure 
> out what command has been run and handle it accordingly? I think that's 
> what the node-sftp library does (example code below).
> This seems like an alien way of doing things for me but I guess it's 
> similar to handling a request from a browser and determining what script 
> needs to handle the request.
>
>     /**
>      * Parse the STDOUT of the sftp child process, collect the lines of 
> data for
>      * the active command and detect if the active command has finished 
> executing.
>      * If the active command is done, respective callbacks are called.
>      * 
>      * @param {String} data
>      * @type  {void}
>      * @private
>      */
>     function parseReply(data) {
>         //console.log("data: ", data, data.split("\n").length + " parts");
>         this.emit("data", data);
>         if (!this.activeCmd && !(this.state & Sftp.STATE_CONNECTING))
>             return;
>         var cbdone, cbprogress;
>         if (data.indexOf("sftp>") > -1 || (this.activeCmd == "bye" && 
> data.indexOf("bye") > -1)) {
>             if (this.state & Sftp.STATE_CONNECTING && 
> this.callbacks["connect"]) {
>                 this.callbacks["connect"]();
>                 delete this.callbacks["connect"];
>             }
>             // check if a command has finished executing:
>             else if (cbdone = this.callbacks[this.activeCmd]) {
>                 delete this.callbacks[this.activeCmd];
>                 delete this.callbacks[this.activeCmd + "_progress"];
>                 this.activeCmd = null;
>                 cbdone((this.activeCmdBuffer + 
> data).split(/[\n\r]+/).filter(function(line) {
>                     return line.indexOf("sftp>") === -1;
>                 }));
>                 this.activeCmdBuffer = "";
>             }
>             if (!this.activeCmd && this.queue.length && this.state & 
> Sftp.STATE_CONNECTED)
>                 this.exec.apply(this, this.queue.shift());
>         }
>         else if (cbprogress = this.callbacks[this.activeCmd + 
> "_progress"]) {
>             this.activeCmdBuffer += data;
>             cbprogress(data);
>         }
>     }
>
>
> On Monday, 30 July 2012 21:23:35 UTC+1, rhasson wrote:
>>
>> "stdin" and "stdout" available on the child process are buffer that 
>> inherit from EventEmitter (well they are streams, unless you change their 
>> behavior when creating the spawned child).  As mentioned by Dominic you 
>> need to add event listeners to the data events of the stdout and stderr so 
>> you can see what the FTP process writes.  You then need to parse it and 
>> write to the stdin stream while again listening to the stdout and making 
>> sure you received the complete response to the command you sent.
>>
>> just  be careful not to get into a situation, as you have in your 
>> example, where you register multiple listeners to the same event performing 
>> different tasks.  In your example, the outer and inner listeners on stdout 
>> data event will be called when you write "ls" and when you write "rename". 
>>  You'll get into an infinite loop very quickly.
>>
>> I think you need to create a single data handler that will deal with 
>> processing of all expected output from the FTP process based on all 
>> possible FTP commands you plan to use.  Try to make it as generic as 
>> possible so regardless if you did "ls /tmp" or "ls /home" the processing 
>> within the data handler will be the same.  You'll need to maintain some 
>> structure outside of the data handler to deal with passing that information 
>> back to the calling function (via callbacks or events).
>>
>> If you really want to you can build a TCP server instead that implements 
>> the FTP protocol.  Maybe even easier is to copy what other FTP modules did 
>> and just refresh the code and make it your own.
>>
>> Roy
>>
>> On Monday, July 30, 2012 7:01:43 AM UTC-4, carlton wrote:
>>>
>>> Hi there,
>>>
>>> I am trying to implent a nodejs script that connects to one of our 
>>> servers using sftp.
>>>
>>> So far I can connect using child process and spawning a command such 
>>> as...
>>>
>>> sftp -o Port=22-o PasswordAuthentication=no-o 
>>> UserKnownHostsFile=/home/carlton/.ssh/known_hosts-o 
>>> IdentityFile=private_key-o StrictHostKeyChecking=no-o 
>>> BatchMode=nodeploy@46.x.x.x:/home/carlton/to_process
>>>
>>> Now this is the part that has me confused...
>>>
>>> I then need to execute commands on the ftp server (e.g. list files, 
>>> rename files) so I listen to the 'data' event....
>>>
>>> sftp.stdout.on('data', function (data) {
>>>     console.log('stdout: ' + data);
>>>
>>>     sftp.stdin.write("ls -l\r\n");
>>>
>>>     sftp.stdout.on('data', function(data){
>>>         console.log('File list:', data.toString());
>>>         
>>>          // Parse file names here
>>>          
>>>         sftp.stdin.write("rename 
>>> /home/carlton/FTP_test/to_process/old.php /home/ carlton 
>>> /FTP_test/processed/new.php\n");
>>>     });
>>> });
>>>
>>> Is this the correct way to structure things (i.e. creatiung event 
>>> listener again for the 'data' event within the callback of the previous 
>>> 'data' event listener)?
>>> I found it hard to find any examples similar to what I need to do which 
>>> made me think I haven't built this as it should have been.
>>>
>>

-- 
Job Board: http://jobs.nodejs.org/
Posting guidelines: 
https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
You received this message because you are subscribed to the Google
Groups "nodejs" group.
To post to this group, send email to nodejs@googlegroups.com
To unsubscribe from this group, send email to
nodejs+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/nodejs?hl=en?hl=en

Reply via email to