Skip to content

Commit 26c63e2

Browse files
committed
Support folder upload
1 parent 1168445 commit 26c63e2

File tree

2 files changed

+58
-9
lines changed

2 files changed

+58
-9
lines changed

AutoSSHApp.cs

Lines changed: 55 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ public override string ToString()
4141
private static SecureString userName;
4242
private static SecureString password;
4343
private static long bytesDownloaded;
44+
private static long bytesUploaded;
4445
private static long bytesSkipped;
4546

4647
private static void WriteSecure(SecureString secureString, ShellStream writer)
@@ -164,9 +165,9 @@ private static List<KeyValuePair<HostEntry, List<string>>> LoadCommands(string c
164165
return commands;
165166
}
166167

167-
private static List<KeyValuePair<HostEntry, List<string>>> Initialize(string commandFile, string root)
168+
private static List<KeyValuePair<HostEntry, List<string>>> Initialize(string commandFile, string backupRoot)
168169
{
169-
string loginPath = Path.Combine(root, "login.key");
170+
string loginPath = Path.Combine(backupRoot, "login.key");
170171
if (!File.Exists(loginPath))
171172
{
172173
Console.Write("Enter user name: ");
@@ -372,12 +373,47 @@ private static long BackupFolder(HostEntry host, string root, string path, SftpC
372373
return size;
373374
}
374375

376+
private static long UploadFolder(HostEntry host, string pathInfo, SftpClient client, StreamWriter log)
377+
{
378+
long uploadSize = 0;
379+
string[] paths = pathInfo.Split(';');
380+
string localDir = paths[0];
381+
string remoteFolder = paths[1];
382+
string[] localFiles = Directory.GetFiles(localDir, "*", SearchOption.AllDirectories);
383+
Parallel.ForEach(localFiles, file =>
384+
{
385+
if (host.IgnoreRegex != null && host.IgnoreRegex.IsMatch(file))
386+
{
387+
return;
388+
}
389+
390+
using var stream = File.OpenRead(file);
391+
var localDirForFile = Path.GetDirectoryName(file);
392+
var localFile = Path.GetFileName(file);
393+
var remoteDir = Path.Combine(remoteFolder, localDirForFile.Substring(localDir.Length));
394+
var remoteFile = remoteDir + "/" + localFile;
395+
if (!client.Exists(remoteDir))
396+
{
397+
client.CreateDirectory(remoteDir);
398+
}
399+
long prevProgress = 0;
400+
client.UploadFile(stream, remoteFile, bytesUploaded =>
401+
{
402+
Interlocked.Add(ref AutoSSHApp.bytesUploaded, ((long)bytesUploaded - prevProgress));
403+
prevProgress = (long)bytesUploaded;
404+
});
405+
Interlocked.Add(ref uploadSize, prevProgress);
406+
});
407+
return uploadSize;
408+
}
409+
375410
private static void ClientLoop(string root, HostEntry host, List<string> commands)
376411
{
377412
bytesDownloaded = 0;
378413
string logFile = Path.Combine(root, host.Name, "log.txt");
379414
string backupPath = Path.Combine(root, host.Name, "backup");
380415
long backupSize = 0;
416+
long uploadSize = 0;
381417
Directory.CreateDirectory(Path.GetDirectoryName(logFile));
382418
Regex promptRegex = new Regex(@"[$>]");
383419
//Regex userRegex = new Regex(@"[$>]");
@@ -420,6 +456,10 @@ private static void ClientLoop(string root, HostEntry host, List<string> command
420456
{
421457
backupSize += BackupFolder(host, backupPath, command.Substring(8), sftpClient, writer);
422458
}
459+
else if (command.StartsWith("$upload ", StringComparison.OrdinalIgnoreCase))
460+
{
461+
uploadSize += UploadFolder(host, command.Substring(8), sftpClient, writer);
462+
}
423463
else if (command.StartsWith("$ignore ", StringComparison.OrdinalIgnoreCase))
424464
{
425465
host.IgnoreRegex = new Regex(command.Substring(8), RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
@@ -446,7 +486,8 @@ private static void ClientLoop(string root, HostEntry host, List<string> command
446486
}
447487
writer.Write("logout\n");
448488
}
449-
Console.WriteLine("{0} backed up {1} ", host, BytesToString(backupSize));
489+
Console.WriteLine("{0} backed up {1} ", host, BytesToString(backupSize));
490+
Console.WriteLine("{0} uploaded {1} ", host, BytesToString(uploadSize));
450491
}
451492

452493
public static void Main(string[] args)
@@ -457,17 +498,20 @@ public static void Main(string[] args)
457498
}
458499

459500
Console.WriteLine("Process started at {0}", DateTime.Now);
501+
ThreadPool.SetMinThreads(1024, 2048);
502+
ThreadPool.SetMaxThreads(16384, 32768);
460503
Stopwatch stopWatch = Stopwatch.StartNew();
461-
string commandFile = args[0];
462-
string backupFolder = args[1];
504+
string commandFile = args.Length > 0 ? args[0] : null;
505+
string backupFolder = args.Length > 1 ? args[1] : null;
463506
List<KeyValuePair<HostEntry, List<string>>> commands = Initialize(commandFile, backupFolder);
464507
Timer updateTimer = new Timer(new TimerCallback((state) =>
465508
{
466-
Console.Write("Bytes downloaded: {0}, skipped: {1} \r", BytesToString(bytesDownloaded), BytesToString(bytesSkipped));
509+
Console.Write("Bytes downloaded: {0}, uploaded: {1}, skipped: {2} \r",
510+
BytesToString(bytesDownloaded), BytesToString(bytesUploaded), BytesToString(bytesSkipped));
467511
}));
468512

469-
// 10x second update rate
470-
updateTimer.Change(1, 100);
513+
// 4x second update rate
514+
updateTimer.Change(1, 250);
471515
Parallel.ForEach(commands, (kv) =>
472516
{
473517
try
@@ -479,7 +523,9 @@ public static void Main(string[] args)
479523
Console.WriteLine("Error on host {0}: {1}\r\n", kv.Key.Host, ex);
480524
}
481525
});
482-
Console.WriteLine("Bytes downloaded: {0}, skipped: {1} ", BytesToString(bytesDownloaded), BytesToString(bytesSkipped));
526+
Console.WriteLine("Bytes downloaded: {0} ", BytesToString(bytesDownloaded));
527+
Console.WriteLine("Bytes uploaded: {0} ", BytesToString(bytesUploaded));
528+
Console.WriteLine("Bytes skipped: {0} ", BytesToString(bytesSkipped));
483529
Console.WriteLine("Process completed at {0}, total time: {1:0.00} minutes.", DateTime.Now, stopWatch.Elapsed.TotalMinutes);
484530
}
485531
}

Readme.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ $ignore big_file[0-9]+\.bin
3131
# backup files and folders, always recursive, separate multiple with |
3232
$backup /var/www|/etc/apache2/apache2.conf|/etc/apache2/sites-enabled
3333
34+
# upload files and folders, always recursive, separate local and remote path with a ;
35+
$upload c:/files/newfiles;/home/user/newfiles
36+
3437
# hosts have a name and an address/dns name
3538
# when backing up, the hostname will be used for the folder name inside the root backup folder.
3639
$host hostname hostaddress

0 commit comments

Comments
 (0)