SFTP Deployer

Script di automazione per l'upload su server multipli tramite sFTP.
PHP, JSON - 2018

JSON Config file

Un estratto del file di configurazione che contiene le pagine di cui aggiungere i metatag definiti.

            
            {
                "servers":
                {
                    "<ip address 1>":
                    {
                        "name": "Server 1 name"
                        ,"port" : 22
                        ,"remote_base_dir" : "/var/www/..."
                        ,"username" : "username"
                        ,"password" : "password"
                    },
                    "<ip address 2>":
                    {
                        "name": "Server 2 name"
                        ,"port" : 22
                        ,"remote_base_dir" : "/var/www/..."
                        ,"username" : "username"
                        ,"password" : "password"
                    }
                },

                "folders_to_upload":
                [
                    "folder1"
                    ,"folder2"
                    ,"public"
                ],
                "folders_to_create":
                {
                    "public/subfolder1":"0775"
                    ,"public/subfolder2":"0775"
                },
                "folders_to_exclude":
                [
                    "folder1/subfolder1"
                    ,"folder1/subfolder2/subsubfolder1"
                ],
                "files_to_exclude":
                [
                    "folder1/file1.html"
                    ,".gitignore"
                ]
            }
            
            

Login

La funzione autentica al server tramite ssh e restituisce l'handle sftp per poter utilizzare i comandi sFTP

            
            /*
             * $sftp = login('192.168.1.22', 22, 'username', 'password');
             */
            function login($host, $port, $username, $password)
            {
                $connection = ssh2_connect($host, $port);
                if (!$connection)
                {
                    echo "Could not connect to $host on port $port.";
                    return false;
                }

                if (! ssh2_auth_password($connection, $username, $password))
                {
                    echo "Could not authenticate with username: $username";
                    return false;
                }
                $sftp = ssh2_sftp($connection);
                if (! $sftp)
                {
                    echo "Could not initialize SFTP subsystem";
                    return false;
                }
                return $sftp;
            }
            
            

Upload single file

La funzione effettua l'upload di un file

            
            /*
             * $sftp = ...;
             * uploadFile($sftp, '/var/www/html/public/index.html', 'var/www/site_1/public/index.html');
             */
            function uploadFile(&$sftp, $local_file, $remote_file)
            {
                if (!file_exists($local_file)) return false;

                $stream = @fopen("ssh2.sftp://$sftp$remote_file", 'w');

                if (!$stream)
                {
                    if (!@mkdir("ssh2.sftp://$sftp".dirname($remote_file), 0775, true))
                    {
                        echo "Could not create folder: ".dirname($remote_file);
                        return false;
                    }
                    $stream = @fopen("ssh2.sftp://$sftp$remote_file", 'w');
                }
                if (! $stream)
                {
                    echo "Could not open file: $remote_file";
                    return false;
                }

                $data_to_send = @file_get_contents($local_file);
                if ($data_to_send === false)
                {
                    echo "Could not open local file: $local_file.";
                    return false;
                }

                if (@fwrite($stream, $data_to_send) === false)
                {
                    echo "Could not send data from file: $local_file.";
                    return false;
                }

                @fclose($stream);
                return true;
            }
            
            

Create remote folder

La funzione permette di creare una cartella sul server remoto

            

            /*
             * $sftp = ...;
             * createFolder($sftp, 'public/resources','0775');
             */
            function createFolder(&$sftp, $folder, $mode)
            {
                if (file_exists("ssh2.sftp://$sftp$folder"))
                {
                    return true;
                }
                if (!@mkdir("ssh2.sftp://$sftp$folder", intval($mode, 8), true))
                {
                    echo "Could not create folder: $folder";
                    return false;
                }
                return true;
            }
            
            

Upload entire folder

La funzione permette di effettuare l'upload di una cartella. E' possibile specificare i nomi delle cartelle da escludere ed i file

            
            /*
             * $sftp = ...;
             * uploadFolder(  $sftp
                            , '/var/www/html'
                            , '/var/www/site_1'
                            , 'public'
                            , array(
                                'public/private_subfolder'
                            )
                            , array(
                                'public/private_file.txt'
                            )
                        );
             */
            function uploadFolder(&$sftp, $local_base_folder, $remote_base_folder, $folder_to_upload, $exclude_folders=null, $exclude_files=null)
            {
                if (substr($local_base_folder, strlen($local_base_folder) - 1, 1) != '/')
                {
                    $local_base_folder .= '/';
                }
                if (substr($folder_to_upload, strlen($folder_to_upload) - 1, 1) != '/')
                {
                    $folder_to_upload .= '/';
                }


                $files = glob($local_base_folder.$folder_to_upload.'{,.}*', GLOB_BRACE);
                
                foreach ($files as $file)
                {
                    if ($file == $local_base_folder.$folder_to_upload.'.') continue;
                    if ($file == $local_base_folder.$folder_to_upload.'..') continue;
                    if (is_dir($file))
                    {
                        $folder_must_be_excluded = false;

                        if ($exclude_folders)
                        {
                            for($i=0;$i<count($exclude_folders);$i++)
                            {
                                if ($local_base_folder.$exclude_folders[$i] == $file)
                                {
                                    $folder_must_be_excluded = true;
                                    break;
                                }
                            }
                        }

                        if (!$folder_must_be_excluded)
                        {
                            uploadFolder($sftp, $local_base_folder, $remote_base_folder, $folder_to_upload.basename($file), $exclude_folders, $exclude_files);
                        }
                    }
                    else
                    {
                        $file_must_be_excluded = false;
                        for($i=0;$i<count($exclude_files);$i++)
                        {
                            if ($local_base_folder.$exclude_files[$i] == $file)
                            {
                                $file_must_be_excluded = true;
                                break;
                            }
                        }

                        if (!$file_must_be_excluded)
                        {
                            uploadFile($sftp, $file, $remote_base_folder.$folder_to_upload.basename($file), $folder_to_upload);
                        }
                    }
                }
            }


            
            

Esempio

            

			function do_deploy_on_server($ip
						, $server_name
						, $port
						, $uname
						, $password
						, $remote_base_dir
						, $local_basedir
						, $folders_to_create
						, $folders_to_upload
						, $folders_to_exclude
						, $files_to_exclude)
			{
			    try
			    {
			        $start_tstamp = time();
			        
			        $sftp = login($ip, $port, $uname, $password);
			        
			        foreach($folders_to_create as $folder_to_create => $mode)
			        {
			            createFolder($sftp, $remote_base_dir.$folder_to_create, $mode);
			        }
			        
			        for($i=0;$i<count($folders_to_upload);$i++)
			        {
			            uploadFolder($sftp, $local_basedir
			                , $remote_base_dir
			                , $folders_to_upload[$i]
			                , $folders_to_exclude
			                , $files_to_exclude
			            );
			        }
			        
			        $dur_tot = time() - $start_tstamp;
			        $mins = intval(($dur_tot) / (60), 10);
			        $hrs = 0;
			        if ($mins >= 60) $hrs = intval($mins / 60, 10);
			        $mins = $mins - ($hrs*60);
			        $secs = $dur_tot - ($mins*60) - ($hrs*3600);
			        echo "\r\nELAPSED TIME:\t\t".$hrs.'h '.$mins.'m '.$secs.'s';
			        echo "\r\nSTART:\t\t\t".date('d M Y H:i:s', $start_tstamp).' >> ('.$start_tstamp.")";
			        echo "\r\nEND:\t\t\t".date('d M Y H:i:s').' >> ('.time().")\r\n";
			    }
			    catch (Exception $e)
			    {
			        echo "!!! ".$e->getMessage() . "\r\n";
			    }
			}


			// ==================================================================
			// MAIN

			...
			$config = json_decode(file_get_contents('config.json'), true);

			$servers = $config['servers'];

			$folders_to_create = $config['folders_to_create'];
			$folders_to_upload = $config['folders_to_upload'];
			$folders_to_exclude = $config['folders_to_exclude'];
			$files_to_exclude = $config['files_to_exclude'];

			foreach ($servers as $ip => $values)
			{
				do_deploy_on_server($ip
					, $values['name']
					, $values['port']
					, $values['username']
					, $values['password']
					, $values['remote_base_dir']
					, $local_basedir
					, $folders_to_create
					, $folders_to_upload
					, $folders_to_exclude
					, $files_to_exclude);
			}