Topic "Automate SCP push of a single file to multiple hosts"

Author Message
solutionsville
[View user's profile]

Joined: 2016-10-20
Posts: 18
Location: Ft Worth
I need to move a single file to about 700 hosts. These hosts do not support SFTP, only SCP.

I created a .NET assembly code from WinSCP, compiled it and ran it. It threw an error on the Session Options portion. Here is the generated code;

Code:

using System;
using WinSCP;

namespace PushFirmware
{
    class Program
    {
        static void Main(string[] args)
        {
            {
                // Set up session options
                SessionOptions sessionOptions = new SessionOptions
                {
                    Protocol = Protocol.Scp,
                    HostName = "192.168.1.100",
                    UserName = "root",
                    Password = "<password>",
                    SshHostKeyFingerprint = "ssh-rsa 1040 xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx",
                };

                using (Session session = new Session())
                {
                    // Connect
                    session.Open(sessionOptions);

                    // Transfer Files
                    session.PutFiles(@"C:\CNA1000\Firmware\CNA1504v1.1.7\CNA1504v1_1_7.run", "/var/tmp/*").Check();
                }
            }
        }
    }
}


It hits with an unhandled exception of type 'WinSCP.SessionRemoteException' occurred in WinSCPnet.dll

Additional information: Key-exchanged algorithm diffie-hellman-group1-sha1 was not verified.

So, first, I am stuck on getting a single file to run with .NET.

I can do a single file from a command prompt with PSCP.exe like this;


Code:

echo y | pscp –pw <password> -v –scp C:\CNA1000\Firmware\CNA1504v1.1.7\CNA1504v1_1_7.run root@192.168.1.100:/tmp/.


But I cannot do that as a batch file with multiple lines.

Thanks,
Advertisements
martin
[View user's profile]
Site Admin
Joined: 2002-12-10
Posts: 25748
Location: Prague, Czechia
If some of your hosts support only the deprecated KEX "diffie-hellman-group1-sha1", you have to explicitly allow it.
See https://winscp.net/forum/viewtopic.php?t=23553
solutionsville
[View user's profile]

Joined: 2016-10-20
Posts: 18
Location: Ft Worth
Thanks Martin, that worked. Now I just need set it up for multiple sites. I will post sample code when I am done.
solutionsville
[View user's profile]

Joined: 2016-10-20
Posts: 18
Location: Ft Worth
Martin, I have been successful at pushing the file to multiple hosts. In the example below it is just to two sites;

I created a C# Console app called PushFirmware. I added the WinSCP API as a reference, and then in the code below, it will connect to both devices and send the file to each.

I need to add the code so that the PLINK command can execute a shell script on the Linux devices and install the firmware. Lastly, is to add Try/Catch to catch any issues.

I will update the code once I have completed and tested it.

Code:

Program.cs
using System;
using System.Collections.Concurrent;
using System.IO;
using System.Threading;

namespace PushFirmware
{
    class Program
    {
        static ConcurrentQueue<string> ConsoleQueue;
        static System.Timers.Timer timer;
        static void Main()
        {
            timer = new System.Timers.Timer(200);
            timer.Elapsed += Timer_Elapsed;
            timer.Enabled = true;
            ConsoleQueue = new ConcurrentQueue<string>();
            Console.WriteLine("Transfering Binaries to CNA's");

            //Threading thr1 = new Threading();
            UploadTask thr1 = new UploadTask("192.168.1.100", "ssh-rsa 1040 <insert SSHKEY here>", ConsoleQueue);
            UploadTask thr2 = new UploadTask("192.168.1.101", "ssh-rsa 1040 <insert SSHKEY here>", ConsoleQueue);

            while (true)
            {
                Thread.Sleep(2);
            }
            //timer.Enabled = false;

        }

        private static void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (ConsoleQueue == null) return;
            string s;
            while (ConsoleQueue.TryDequeue(out s)) {
                File.AppendAllText("C:\\test.log", s + Environment.NewLine);
            Console.WriteLine(s);
        }
        }
    }
}


Code:

Threading.cs
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using WinSCP;

namespace PushFirmware
{
    class UploadTask
    {
        ConcurrentQueue<string> ConsoleQueue;
        string cna_ip;
        string fprint;

        public UploadTask(string cip, string fpr, ConcurrentQueue<string> q)
        {
            cna_ip = cip;
            fprint = fpr;
            ConsoleQueue = q;
            start();
        }
        void start()
        {
            Thread tid1 = new Thread(new ThreadStart(Thread1));
            tid1.Start();
        }
        public void Thread1()
        {
            // Set up session options
            SessionOptions sessionOptions = new SessionOptions
            {
                Protocol = Protocol.Scp,
                HostName = cna_ip,
                UserName = "<username>",
                Password = "<password>",
                SshHostKeyFingerprint = fprint
            };

            sessionOptions.AddRawSettings("AuthGSSAPI", "1");
            sessionOptions.AddRawSettings("Cipher", "aes,blowfish,3des,chacha20,WARN,arcfour,des");
            sessionOptions.AddRawSettings("KEX", "ecdh,dh-gex-sha1,dh-group14-sha1,dh-group1-sha1,rsa,WARN");

            using (Session session = new Session())
            {
                // Connect
                session.Open(sessionOptions);
                // Upload files
                TransferOptions transferOptions = new TransferOptions();
                transferOptions.TransferMode = TransferMode.Binary;

                TransferOperationResult transferResult;
                transferResult = session.PutFiles(@"E:\CNA1000\Firmware\CNA1504v1.1.7\CNA1504v1_1_7.run", "/var/tmp/*", false, transferOptions);
                /*
                 catch(Exception ex){ConsoleQueue.Enqueue(ex.Message);}
                 */
//                transferResult.Check();
                session.Close();
                // Print results
                //foreach (TransferEventArgs transfer in transferResult.Transfers)
                //{
                    ConsoleQueue.Enqueue(string.Format("Upload to {0} succeeded", cna_ip));
                //Console.WriteLine("Upload of {0} succeeded", transfer.FileName);
                //}

                // run plink here
                ConsoleQueue.Enqueue("running plink... add the code here to run the plink command and an update script to execute the uploaded file.");
            }
        }
    }
}

martin
[View user's profile]
Site Admin
Joined: 2002-12-10
Posts: 25748
Location: Prague, Czechia
solutionsville wrote:
I need to add the code so that the PLINK command can execute a shell script on the Linux devices and install the firmware. Lastly, is to add Try/Catch to catch any issues.

You can use WinSCP Session.ExecuteCommand instead of the Plink.
https://winscp.net/eng/docs/library_session_executecommand
solutionsville
[View user's profile]

Joined: 2016-10-20
Posts: 18
Location: Ft Worth
This looks promising.

(for executing a Remote Shell Script on Linux)

Not sure how I would run this shell script;
Code:

#/!/bin/bash
#/This script is to install the firmware to the CNA1500/2000
cd /tmp
chmod 777 *.run
./CNA1504v1_1_7.run --load &


Would I break each up into a single command, or am I over thinking this one?

Thanks!
Guest




Martin, I figured out the Execute method.

Is there a way to get any feedback that the command was successfully completed?

Thanks,
guest2

Guest


Anonymous wrote:
Martin, I figured out the Execute method.

Is there a way to get any feedback that the command was successfully completed?

Thanks,


"successful completion" would be indicated by a terminal message saying 'rebooting host' that comes long after the remote command is executed.

the last script command ( "--load" ) begins a lengthy process where a large binary is verified, then applied, and finally the remote host is rebooted. The process takes 1-2 minutes, and during this time a lot of status lines are sent to the terminal.

We were thinking the Session would pick these up, but not having any luck. CommandExecutionResult.Output returns NULL, even when we loop for a minute checking it.
solutionsville
[View user's profile]

Joined: 2016-10-20
Posts: 18
Location: Ft Worth
guest2 wrote:
Anonymous wrote:
Martin, I figured out the Execute method.

Is there a way to get any feedback that the command was successfully completed?

Thanks,


"successful completion" would be indicated by a terminal message saying 'rebooting host' that comes long after the remote command is executed.

the last script command ( "--load" ) begins a lengthy process where a large binary is verified, then applied, and finally the remote host is rebooted. The process takes 1-2 minutes, and during this time a lot of status lines are sent to the terminal.

We were thinking the Session would pick these up, but not having any luck. CommandExecutionResult.Output returns NULL, even when we loop for a minute checking it.


With 700 devices, it is nor practical to have 700 terminal sessions open at the same time, nor do I have the resources to watch 700 open terminals.
martin
[View user's profile]
Site Admin
Joined: 2002-12-10
Posts: 25748
Location: Prague, Czechia
Anonymous wrote:
Is there a way to get any feedback that the command was successfully completed?

You run the command on background (using the &), so the command completes asynchronously. You cannot monitor it.
solutionsville
[View user's profile]

Joined: 2016-10-20
Posts: 18
Location: Ft Worth
martin wrote:
Anonymous wrote:
Is there a way to get any feedback that the command was successfully completed?

You run the command on background (using the &), so the command completes asynchronously. You cannot monitor it.


Thanks! I will take that out and see what it does. I was provided the command by the manufacture.
solutionsville
[View user's profile]

Joined: 2016-10-20
Posts: 18
Location: Ft Worth
martin wrote:
Anonymous wrote:
Is there a way to get any feedback that the command was successfully completed?

You run the command on background (using the &), so the command completes asynchronously. You cannot monitor it.


Martin, this worked fine. However one thing I noticed it seems to take about 90 seconds to close the session. I do call the session.Close(), after the Load is complete. Is it normal for it to take that long or do I need to add something to make it close the session faster?

Thanks,
martin
[View user's profile]
Site Admin
Joined: 2002-12-10
Posts: 25748
Location: Prague, Czechia
It should not take that long.

Please attach a full session log file showing the problem (using the latest version of WinSCP).

To generate the session log file, set Session.SessionLogPath. Submit the log with your post as an attachment. Note that passwords and passphrases not stored in the log. You may want to remove other data you consider sensitive though, such as host names, IP addresses, account names or file names (unless they are relevant to the problem). If you do not want to post the log publicly, you can mark the attachment as private.
solutionsville
[View user's profile]

Joined: 2016-10-20
Posts: 18
Location: Ft Worth
martin wrote:
It should not take that long.

Please attach a full session log file showing the problem (using the latest version of WinSCP).

To generate the session log file, set Session.SessionLogPath. Submit the log with your post as an attachment. Note that passwords and passphrases not stored in the log. You may want to remove other data you consider sensitive though, such as host names, IP addresses, account names or file names (unless they are relevant to the problem). If you do not want to post the log publicly, you can mark the attachment as private.


Hi Martin, thanks for the response.

We figured it out. We had added a timer that we thought we needed and turned out not needing. Once we remove out self imposed timer, all worked well.

Thanks,
Advertisements

You can post new topics in this forum






Search Site

What is WinSCP?

It is award-winning SFTP client, SCP client, FTPS client and FTP client integrated into one software program for file transfer to FTP server or secure SFTP server. [More]

And it's free!

Donate

About donations

$9   $19   $49   $99

About donations

Recommend

WinSCP Privacy Policy

WinSCP License