Automate SCP push of a single file to multiple hosts

Advertisement

solutionsville
Joined:
Posts:
19
Location:
Ft Worth

Automate SCP push of a single file to multiple hosts

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;

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;


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,

Reply with quote

Advertisement

solutionsville
Joined:
Posts:
19
Location:
Ft Worth

Re: Automate SCP push of a single file to multiple hosts

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.

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);
        }
        }
    }
}

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.");
            }
        }
    }
}

Reply with quote

martin
Site Admin
martin avatar
Joined:
Posts:
28,671
Location:
Prague, Czechia

Re: Automate SCP push of a single file to multiple hosts

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

Reply with quote

Advertisement

solutionsville
Joined:
Posts:
19
Location:
Ft Worth

Re: Automate SCP push of a single file to multiple hosts

This looks promising.

(for executing a Remote Shell Script on Linux)

Not sure how I would run this shell script;
#/!/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!

Reply with quote

Guest

Re: Automate SCP push of a single file to multiple hosts

Martin, I figured out the Execute method.

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

Thanks,

Reply with quote

guest2
Guest

Re: Automate SCP push of a single file to multiple hosts

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.

Reply with quote

solutionsville
Joined:
Posts:
19
Location:
Ft Worth

Re: Automate SCP push of a single file to multiple hosts

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.

Reply with quote

Advertisement

martin
Site Admin
martin avatar
Joined:
Posts:
28,671
Location:
Prague, Czechia

Re: Automate SCP push of a single file to multiple hosts

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.

Reply with quote

solutionsville
Joined:
Posts:
19
Location:
Ft Worth

Re: Automate SCP push of a single file to multiple hosts

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.

Reply with quote

solutionsville
Joined:
Posts:
19
Location:
Ft Worth

Re: Automate SCP push of a single file to multiple hosts

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,

Reply with quote

martin
Site Admin
martin avatar
Joined:
Posts:
28,671
Location:
Prague, Czechia

Re: Automate SCP push of a single file to multiple hosts

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.

Reply with quote

Advertisement

solutionsville
Joined:
Posts:
19
Location:
Ft Worth

Re: Automate SCP push of a single file to multiple hosts

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,

Reply with quote

Advertisement

You can post new topics in this forum