Skip to content

Instantly share code, notes, and snippets.

@bartvdbraak
Created January 30, 2024 20:07
Show Gist options
  • Save bartvdbraak/9e56d45583b68f994a15d6d18fe76a8e to your computer and use it in GitHub Desktop.
Save bartvdbraak/9e56d45583b68f994a15d6d18fe76a8e to your computer and use it in GitHub Desktop.
(unfinished) Download wwwroot of Linux Web App on Azure using ssh and tar
import os
import sys
import time
import subprocess
import re
import paramiko
from paramiko import SSHClient, AutoAddPolicy
REMOTE_FILE_OUTPUT = "/home/site/wwwroot.tar"
def cleanup(session_name, ssh_client, screen_pid):
try:
ssh_client.exec_command("exit") # Exit the remote session gracefully
ssh_client.close()
print("SSH connection closed.")
except Exception as e:
print(f"Error during cleanup: {str(e)}")
try:
os.remove(f"{session_name}.log") # Remove the log file
print("Log file removed.")
except Exception as e:
print(f"Error removing log file: {str(e)}")
try:
# Terminate the screen session
subprocess.run(f"screen -S {session_name} -X quit", shell=True)
print("Screen session terminated.")
except Exception as e:
print(f"Error terminating screen session: {str(e)}")
print("Script terminated. Cleanup completed.")
def main():
if len(sys.argv) != 4:
print("Usage: python3 backup-wwwroot.py SubscriptionId ResourceGroup AppName")
sys.exit(1)
subscription_id = sys.argv[1]
resource_group = sys.argv[2]
app_name = sys.argv[3]
timestamp = time.strftime("%Y%m%d%H%M%S")
session_name = f"remote-connection-session-{timestamp}"
file_output = f"{app_name}-wwwroot.tar"
try:
# Create a detached screen session for the Azure CLI command
screen_cmd = (
f"screen -S {session_name} -d -m bash -c 'az webapp create-remote-connection "
f"--subscription {subscription_id} --resource-group {resource_group} -n {app_name} "
f"> {session_name}.log 2>&1'"
)
subprocess.run(screen_cmd, shell=True)
print("Azure CLI command started.")
# Wait up to 60 seconds for "SSH is available" message
timeout = 60
elapsed = 0
while elapsed < timeout:
time.sleep(1)
elapsed += 1
# Check if "SSH is available" is in the screen session output file
if os.path.exists(f"{session_name}.log"):
with open(f"{session_name}.log", "r") as log_file:
log_content = log_file.read()
match = re.search(r"SSH is available \{ username: ([^,]+), password: ([^}]+) \}", log_content)
addr_match = re.search(r"Opening tunnel on addr: (\S+)", log_content)
port_match = re.search(r"Opening tunnel on port: (\d+)", log_content)
if match and addr_match and port_match:
username = match.group(1).strip()
password = match.group(2).strip()
addr = addr_match.group(1).strip()
port = port_match.group(1).strip()
print("SSH connection details retrieved.")
break
if elapsed >= timeout:
print(f"Unable to establish a connection within {timeout} seconds.")
sys.exit(1)
# Establish SSH connection to the Azure Web App using extracted details
ssh_client = SSHClient()
ssh_client.set_missing_host_key_policy(AutoAddPolicy())
ssh_client.connect(
hostname=addr, # Extracted addr
port=int(port), # Extracted port
username=username, # Extracted username
password=password # Extracted password
)
print("SSH connection established.")
# Execute the command on the remote server to tar the files
stdin, stdout, stderr = ssh_client.exec_command(f"tar -c --warning=no-file-changed -f {REMOTE_FILE_OUTPUT} --totals /home/site/wwwroot", get_pty=True)
print("Tar command is being executed. Waiting for it to finish...")
# Wait for the command to finish
exit_status = stdout.channel.recv_exit_status()
# Check the exit status
if exit_status == 0:
print("Command executed successfully")
else:
print(f"Command failed with exit status {exit_status}")
print("Files on the remote server are archived.")
# Create an SFTP session for file transfer
sftp = ssh_client.open_sftp()
# Copy the tar file to the local machine
sftp.get(REMOTE_FILE_OUTPUT, f"{app_name}-wwwroot.tar")
print("Files copied successfully from the remote server.")
except Exception as e:
print(f"Error: {str(e)}")
print("Unable to establish a connection or transfer files.")
finally:
cleanup(session_name, ssh_client, os.getpid())
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment