So I’m trying use the SYNC
Redis command over an ssh session from a PowerShell script to sync data between a master-replica Redis databases (which are hosted on remote Linux hosts). Due to the infrastructure my project has, I cannot have these two databases as a master-replica relationship, so these databases are both masters. So part of this process involves setting a temporary master-replica relation ship between the two DBs to able to do the SYNC
.
So the flow of the script is:
- Opens a SSH connection to the replica server.
- Get into Redis-cli tool and Run
SLAVEOF $masterServer $masterPort
to create the master-replica relationship. - Run SYNC to sync data between the master-replica.
- Undo the relationship master – replica and set it to be none replication by running SLAVEOF NO ONE on the replica server.
There’s two issues:
- When the
SYNC
is executed it fails with the following error:
SYNC with master failed: -NOMASTERLINK Can't SYNC while not connected with my master
which doesn’t makes sense if we check the entire script log output:
18:35:39 Output : {OK}
18:35:39 ExitStatus : 0
18:35:39 Error :
18:35:39 Host : x.x.x.x
18:35:39 Duration : 00:00:00.2536566
18:35:39
18:35:39
18:35:39 Output : {Entering replica output mode... (press Ctrl-C to quit)}
18:35:39 ExitStatus : 1
18:35:39 Error : SYNC with master failed: -NOMASTERLINK Can't SYNC while not connected with my master
18:35:39
18:35:39 Host : x.x.x.x
18:35:39 Duration : 00:00:00.1155349
The first {OK}
status output is from setting the master-replica relationship. I can confirm that is working because if I execute the script again without undoing the the master-replica relationship, instead {OK}
status it says {OK Already connected to specified master}
.
Initially I suspected that it was an async issue, thinking that the SYNC
was executed to fast before the echo SLAVEOF $masterServer $masterPort | redis-cli
finishes, but it does not explains what status messages I just mentioned nor the following issues #2. (Though I don’t know how to handle async processes on linux/bash)
- If I set manually the master-replica relationship to just test the
SYNC
command, it times out with this error:
ForEach-Object : Exception calling "EndExecute" with "1" argument(s): "Command 'echo SYNC | redis-cli' has timed out."
This might be related to the fact that when theSYNC
command finishes, it puts the bash in a listening state just listening to sequential pings suggesting that connection works, but for escaping this state I must send a Ctrl + C combination which I don’t know how to do. I’ve tried to sendsend -- x03
as an extra command but it does not work. Any idea of how to do this?
Powershell Script:
param(
[Parameter(Mandatory=$true, Position=0)]
[string] $MasterServer,
[Parameter(Mandatory=$true, Position=1)]
[string] $MasterPort,
[Parameter(Mandatory=$true, Position=2)]
[string] $ReplicaServer,
[Parameter(Mandatory=$true, Position=3)]
[string] $UserReplicaServer,
[Parameter(Mandatory=$true, Position=4)]
[string] $PwdReplicaServer
)
$SecurePasswd = ConvertTo-SecureString $PwdReplicaServer -AsPlainText -Force
$Credentials = New-Object System.Management.Automation.PSCredential($UserReplicaServer, $SecurePasswd)
Write-Host "Connecting to Redis host over SSH..."
# Connect Over SSH and getting session id.
$SessionID = New-SSHSession -ComputerName $ReplicaServer -Credential $Credentials -Force
if($SessionID -eq $null){
Write-Host "Error: An error occurred trying to setup the SSH session. Please check the connection string/credentials for the SSH session."
exit 1
} else {
Write-Host "SSH session created successfully. Running Redis SYNC."
}
# Commands.
$commands = @(
@{
Command = "echo SLAVEOF $MasterServer $MasterPort | redis-cli"
Description = "Configure replication"
},
@{
Command = "echo SYNC | redis-cli"
Description = "Sync replication"
},
@{
Command = "echo SLAVEOF NO ONE | redis-cli"
Description = "Undo replication"
}
)
# Execute commands on Redis Host
foreach ($command in $commands) {
$result = Invoke-SSHCommand -Index $SessionID.sessionid -Command $command.Command
if ($result.ExitStatus -ne 0) {
Write-Host "Error: Failed to execute command '$($command.Command)'. Description: $($command.Description) Error message: $($result.StandardError)"
exit 1
}
Write-Host "Success: Command '$($command.Command)' executed successfully. Description: $($command.Description)"
}
Write-Host "Script Worked and Finished!"
2
Answers
Some modifications to the commands and adding
trap '' INT
to execute a Ctrl+C worked.Here is a rewrite, I can’t be of much help with as to the reason why without actually doing a hands on. But hopefully this helps you a bit.
Here is a re-write that focuses on