如何编写shell脚本将VPS上的数据备份到Dropbox网盘
发表于:2025-01-24 作者:千家信息网编辑
千家信息网最后更新 2025年01月24日,本篇内容主要讲解"如何编写shell脚本将VPS上的数据备份到Dropbox网盘",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"如何编写shell脚本将VP
千家信息网最后更新 2025年01月24日如何编写shell脚本将VPS上的数据备份到Dropbox网盘
本篇内容主要讲解"如何编写shell脚本将VPS上的数据备份到Dropbox网盘",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"如何编写shell脚本将VPS上的数据备份到Dropbox网盘"吧!
#!/usr/bin/env bash## Dropbox Uploader## Copyright (C) 2010-2014 Andrea Fabrizi## This program is free software; you can redistribute it and/or modify# it under the terms of the GNU General Public License as published by# the Free Software Foundation; either version 2 of the License, or# (at your option) any later version.## This program is distributed in the hope that it will be useful,# but WITHOUT ANY WARRANTY; without even the implied warranty of# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the# GNU General Public License for more details.## You should have received a copy of the GNU General Public License# along with this program; if not, write to the Free Software# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.##Default configuration fileCONFIG_FILE=~/.dropbox_uploader#Default chunk size in Mb for the upload process#It is recommended to increase this value only if you have enough free space on your /tmp partition#Lower values may increase the number of http requestsCHUNK_SIZE=4#Curl location#If not set, curl will be searched into the $PATH#CURL_BIN="/usr/bin/curl"#Default valuesTMP_DIR="/tmp"DEBUG=0QUIET=0SHOW_PROGRESSBAR=0SKIP_EXISTING_FILES=0ERROR_STATUS=0#Don't edit these...API_REQUEST_TOKEN_URL="https://api.dropbox.com/1/oauth/request_token"API_USER_AUTH_URL="https://www2.dropbox.com/1/oauth/authorize"API_ACCESS_TOKEN_URL="https://api.dropbox.com/1/oauth/access_token"API_CHUNKED_UPLOAD_URL="https://api-content.dropbox.com/1/chunked_upload"API_CHUNKED_UPLOAD_COMMIT_URL="https://api-content.dropbox.com/1/commit_chunked_upload"API_UPLOAD_URL="https://api-content.dropbox.com/1/files_put"API_DOWNLOAD_URL="https://api-content.dropbox.com/1/files"API_DELETE_URL="https://api.dropbox.com/1/fileops/delete"API_MOVE_URL="https://api.dropbox.com/1/fileops/move"API_COPY_URL="https://api.dropbox.com/1/fileops/copy"API_METADATA_URL="https://api.dropbox.com/1/metadata"API_INFO_URL="https://api.dropbox.com/1/account/info"API_MKDIR_URL="https://api.dropbox.com/1/fileops/create_folder"API_SHARES_URL="https://api.dropbox.com/1/shares"APP_CREATE_URL="https://www2.dropbox.com/developers/apps"RESPONSE_FILE="$TMP_DIR/du_resp_$RANDOM"CHUNK_FILE="$TMP_DIR/du_chunk_$RANDOM"TEMP_FILE="$TMP_DIR/du_tmp_$RANDOM"BIN_DEPS="sed basename date grep stat dd mkdir"VERSION="0.14"umask 077#Check the shellif [ -z "$BASH_VERSION" ]; then echo -e "Error: this script requires the BASH shell!" exit 1fishopt -s nullglob #Bash allows filename patterns which match no files to expand to a null string, rather than themselvesshopt -s dotglob #Bash includes filenames beginning with a "." in the results of filename expansion#Look for optional config file parameterwhile getopts ":qpskdf:" opt; do case $opt in f) CONFIG_FILE=$OPTARG ;; d) DEBUG=1 ;; q) QUIET=1 ;; p) SHOW_PROGRESSBAR=1 ;; k) CURL_ACCEPT_CERTIFICATES="-k" ;; s) SKIP_EXISTING_FILES=1 ;; \?) echo "Invalid option: -$OPTARG" >&2 exit 1 ;; :) echo "Option -$OPTARG requires an argument." >&2 exit 1 ;; esacdoneif [[ $DEBUG != 0 ]]; then echo $VERSION set -x RESPONSE_FILE="$TMP_DIR/du_resp_debug"fiif [[ $CURL_BIN == "" ]]; then BIN_DEPS="$BIN_DEPS curl" CURL_BIN="curl"fi#Dependencies checkwhich $BIN_DEPS > /dev/nullif [[ $? != 0 ]]; then for i in $BIN_DEPS; do which $i > /dev/null || NOT_FOUND="$i $NOT_FOUND" done echo -e "Error: Required program could not be found: $NOT_FOUND" exit 1fi#Check if readlink is installed and supports the -m option#It's not necessary, so no problem if it's not installedwhich readlink > /dev/nullif [[ $? == 0 && $(readlink -m "//test" 2> /dev/null) == "/test" ]]; then HAVE_READLINK=1else HAVE_READLINK=0fi#Forcing to use the builtin printf, if it's present, because it's better#otherwise the external printf program will be used#Note that the external printf command can cause character encoding issues!builtin printf "" 2> /dev/nullif [[ $? == 0 ]]; then PRINTF="builtin printf" PRINTF_OPT="-v o"else PRINTF=$(which printf) if [[ $? != 0 ]]; then echo -e "Error: Required program could not be found: printf" fi PRINTF_OPT=""fi#Print the message based on $QUIET variablefunction print{ if [[ $QUIET == 0 ]]; then echo -ne "$1"; fi}#Returns unix timestampfunction utime{ echo $(date +%s)}#Remove temporary filesfunction remove_temp_files{ if [[ $DEBUG == 0 ]]; then rm -fr "$RESPONSE_FILE" rm -fr "$CHUNK_FILE" rm -fr "$TEMP_FILE" fi}#Returns the file size in bytes# generic GNU Linux: linux-gnu# windows cygwin: cygwin# raspberry pi: linux-gnueabihf# macosx: darwin10.0# freebsd: FreeBSD# qnap: linux-gnueabi# iOS: darwin9function file_size{ #Some embedded linux devices if [[ $OSTYPE == "linux-gnueabi" || $OSTYPE == "linux-gnu" ]]; then stat -c "%s" "$1" return #Generic Unix elif [[ ${OSTYPE:0:5} == "linux" || $OSTYPE == "cygwin" || ${OSTYPE:0:7} == "solaris" ]]; then stat --format="%s" "$1" return #BSD, OSX and other OSs else stat -f "%z" "$1" return fi}#Usagefunction usage{ echo -e "Dropbox Uploader v$VERSION" echo -e "Andrea Fabrizi - andrea.fabrizi@gmail.com\n" echo -e "Usage: $0 COMMAND [PARAMETERS]..." echo -e "\nCommands:" echo -e "\t upload " echo -e "\t download [LOCAL_FILE/DIR]" echo -e "\t delete " echo -e "\t move " echo -e "\t copy " echo -e "\t mkdir " echo -e "\t list [REMOTE_DIR]" echo -e "\t share " echo -e "\t info" echo -e "\t unlink" echo -e "\nOptional parameters:" echo -e "\t-f Load the configuration file from a specific file" echo -e "\t-s Skip already existing files when download/upload. Default: Overwrite" echo -e "\t-d Enable DEBUG mode" echo -e "\t-q Quiet mode. Don't show messages" echo -e "\t-p Show cURL progress meter" echo -e "\t-k Doesn't check for SSL certificates (insecure)" echo -en "\nFor more info and examples, please see the README file.\n\n" remove_temp_files exit 1}#Check the curl exit codefunction check_http_response{ CODE=$? #Checking curl exit code case $CODE in #OK 0) ;; #Proxy error 5) print "\nError: Couldn't resolve proxy. The given proxy host could not be resolved.\n" remove_temp_files exit 1 ;; #Missing CA certificates 60|58) print "\nError: cURL is not able to performs peer SSL certificate verification.\n" print "Please, install the default ca-certificates bundle.\n" print "To do this in a Debian/Ubuntu based system, try:\n" print " sudo apt-get install ca-certificates\n\n" print "If the problem persists, try to use the -k option (insecure).\n" remove_temp_files exit 1 ;; 6) print "\nError: Couldn't resolve host.\n" remove_temp_files exit 1 ;; 7) print "\nError: Couldn't connect to host.\n" remove_temp_files exit 1 ;; esac #Checking response file for generic errors if grep -q "HTTP/1.1 400" "$RESPONSE_FILE"; then ERROR_MSG=$(sed -n -e 's/{"error": "\([^"]*\)"}/\1/p' "$RESPONSE_FILE") case $ERROR_MSG in *access?attempt?failed?because?this?app?is?not?configured?to?have*) echo -e "\nError: The Permission type/Access level configured doesn't match the DropBox App settings!\nPlease run \"$0 unlink\" and try again." exit 1 ;; esac fi}#Urlencodefunction urlencode{ local string="${1}" local strlen=${#string} local encoded="" for (( pos=0 ; pos /dev/null check_http_response #Even if the file/dir has been deleted from DropBox we receive a 200 OK response #So we must check if the file exists or if it has been deleted if grep -q "\"is_deleted\":" "$RESPONSE_FILE"; then local IS_DELETED=$(sed -n 's/.*"is_deleted":.\([^,]*\).*/\1/p' "$RESPONSE_FILE") else local IS_DELETED="false" fi #Exits... grep -q "^HTTP/1.1 200 OK" "$RESPONSE_FILE" if [[ $? == 0 && $IS_DELETED != "true" ]]; then local IS_DIR=$(sed -n 's/^\(.*\)\"contents":.\[.*/\1/p' "$RESPONSE_FILE") #It's a directory if [[ $IS_DIR != "" ]]; then echo "DIR" #It's a file else echo "FILE" fi #Doesn't exists else echo "ERR" fi}#Generic upload wrapper around db_upload_file and db_upload_dir functions#$1 = Local source file/dir#$2 = Remote destination file/dirfunction db_upload{ local SRC=$(normalize_path "$1") local DST=$(normalize_path "$2") #Checking if the file/dir exists if [[ ! -e $SRC && ! -d $SRC ]]; then print " > No such file or directory: $SRC\n" ERROR_STATUS=1 return fi #Checking if the file/dir has read permissions if [[ ! -r $SRC ]]; then print " > Error reading file $SRC: permission denied\n" ERROR_STATUS=1 return fi #Checking if DST it's a folder or if it doesn' exists (in this case will be the destination name) TYPE=$(db_stat "$DST") if [[ $TYPE == "DIR" ]]; then local filename=$(basename "$SRC") DST="$DST/$filename" fi #It's a directory if [[ -d $SRC ]]; then db_upload_dir "$SRC" "$DST" #It's a file elif [[ -e $SRC ]]; then db_upload_file "$SRC" "$DST" #Unsupported object... else print " > Skipping not regular file \"$SRC\"\n" fi}#Generic upload wrapper around db_chunked_upload_file and db_simple_upload_file#The final upload function will be choosen based on the file size#$1 = Local source file#$2 = Remote destination filefunction db_upload_file{ local FILE_SRC=$(normalize_path "$1") local FILE_DST=$(normalize_path "$2") shopt -s nocasematch #Checking not allowed file names basefile_dst=$(basename "$FILE_DST") if [[ $basefile_dst == "thumbs.db" || \ $basefile_dst == "desktop.ini" || \ $basefile_dst == ".ds_store" || \ $basefile_dst == "icon\r" || \ $basefile_dst == ".dropbox" || \ $basefile_dst == ".dropbox.attr" \ ]]; then print " > Skipping not allowed file name \"$FILE_DST\"\n" return fi shopt -u nocasematch #Checking file size FILE_SIZE=$(file_size "$FILE_SRC") #Checking if the file already exists TYPE=$(db_stat "$FILE_DST") if [[ $TYPE != "ERR" && $SKIP_EXISTING_FILES == 1 ]]; then print " > Skipping already existing file \"$FILE_DST\"\n" return fi if [[ $FILE_SIZE -gt 157286000 ]]; then #If the file is greater than 150Mb, the chunked_upload API will be used db_chunked_upload_file "$FILE_SRC" "$FILE_DST" else db_simple_upload_file "$FILE_SRC" "$FILE_DST" fi}#Simple file upload#$1 = Local source file#$2 = Remote destination filefunction db_simple_upload_file{ local FILE_SRC=$(normalize_path "$1") local FILE_DST=$(normalize_path "$2") if [[ $SHOW_PROGRESSBAR == 1 && $QUIET == 0 ]]; then CURL_PARAMETERS="--progress-bar" LINE_CR="\n" else CURL_PARAMETERS="-s" LINE_CR="" fi print " > Uploading \"$FILE_SRC\" to \"$FILE_DST\"... $LINE_CR" $CURL_BIN $CURL_ACCEPT_CERTIFICATES $CURL_PARAMETERS -i --globoff -o "$RESPONSE_FILE" --upload-file "$FILE_SRC" "$API_UPLOAD_URL/$ACCESS_LEVEL/$(urlencode "$FILE_DST")?oauth_consumer_key=$APPKEY&oauth_token=$OAUTH_ACCESS_TOKEN&oauth_signature_method=PLAINTEXT&oauth_signature=$APPSECRET%26$OAUTH_ACCESS_TOKEN_SECRET&oauth_timestamp=$(utime)&oauth_nonce=$RANDOM" check_http_response #Check if grep -q "^HTTP/1.1 200 OK" "$RESPONSE_FILE"; then print "DONE\n" else print "FAILED\n" print "An error occurred requesting /upload\n" ERROR_STATUS=1 fi}#Chunked file upload#$1 = Local source file#$2 = Remote destination filefunction db_chunked_upload_file{ local FILE_SRC=$(normalize_path "$1") local FILE_DST=$(normalize_path "$2") print " > Uploading \"$FILE_SRC\" to \"$FILE_DST\"" local FILE_SIZE=$(file_size "$FILE_SRC") local OFFSET=0 local UPLOAD_ID="" local UPLOAD_ERROR=0 local CHUNK_PARAMS="" #Uploading chunks... while ([[ $OFFSET != $FILE_SIZE ]]); do let OFFSET_MB=$OFFSET/1024/1024 #Create the chunk dd if="$FILE_SRC" of="$CHUNK_FILE" bs=1048576 skip=$OFFSET_MB count=$CHUNK_SIZE 2> /dev/null #Only for the first request these parameters are not included if [[ $OFFSET != 0 ]]; then CHUNK_PARAMS="upload_id=$UPLOAD_ID&offset=$OFFSET" fi #Uploading the chunk... $CURL_BIN $CURL_ACCEPT_CERTIFICATES -s --show-error --globoff -i -o "$RESPONSE_FILE" --upload-file "$CHUNK_FILE" "$API_CHUNKED_UPLOAD_URL?$CHUNK_PARAMS&oauth_consumer_key=$APPKEY&oauth_token=$OAUTH_ACCESS_TOKEN&oauth_signature_method=PLAINTEXT&oauth_signature=$APPSECRET%26$OAUTH_ACCESS_TOKEN_SECRET&oauth_timestamp=$(utime)&oauth_nonce=$RANDOM" 2> /dev/null check_http_response #Check if grep -q "^HTTP/1.1 200 OK" "$RESPONSE_FILE"; then print "." UPLOAD_ERROR=0 UPLOAD_ID=$(sed -n 's/.*"upload_id": *"*\([^"]*\)"*.*/\1/p' "$RESPONSE_FILE") OFFSET=$(sed -n 's/.*"offset": *\([^}]*\).*/\1/p' "$RESPONSE_FILE") else print "*" let UPLOAD_ERROR=$UPLOAD_ERROR+1 #On error, the upload is retried for max 3 times if [[ $UPLOAD_ERROR -gt 2 ]]; then print " FAILED\n" print "An error occurred requesting /chunked_upload\n" ERROR_STATUS=1 return fi fi done UPLOAD_ERROR=0 #Commit the upload while (true); do $CURL_BIN $CURL_ACCEPT_CERTIFICATES -s --show-error --globoff -i -o "$RESPONSE_FILE" --data "upload_id=$UPLOAD_ID&oauth_consumer_key=$APPKEY&oauth_token=$OAUTH_ACCESS_TOKEN&oauth_signature_method=PLAINTEXT&oauth_signature=$APPSECRET%26$OAUTH_ACCESS_TOKEN_SECRET&oauth_timestamp=$(utime)&oauth_nonce=$RANDOM" "$API_CHUNKED_UPLOAD_COMMIT_URL/$ACCESS_LEVEL/$(urlencode "$FILE_DST")" 2> /dev/null check_http_response #Check if grep -q "^HTTP/1.1 200 OK" "$RESPONSE_FILE"; then print "." UPLOAD_ERROR=0 break else print "*" let UPLOAD_ERROR=$UPLOAD_ERROR+1 #On error, the commit is retried for max 3 times if [[ $UPLOAD_ERROR -gt 2 ]]; then print " FAILED\n" print "An error occurred requesting /commit_chunked_upload\n" ERROR_STATUS=1 return fi fi done print " DONE\n"}#Directory upload#$1 = Local source dir#$2 = Remote destination dirfunction db_upload_dir{ local DIR_SRC=$(normalize_path "$1") local DIR_DST=$(normalize_path "$2") #Creatig remote directory db_mkdir "$DIR_DST" for file in "$DIR_SRC/"*; do db_upload "$file" "$DIR_DST" done}#Returns the free space on DropBox in bytesfunction db_free_quota{ $CURL_BIN $CURL_ACCEPT_CERTIFICATES -s --show-error --globoff -i -o "$RESPONSE_FILE" --data "oauth_consumer_key=$APPKEY&oauth_token=$OAUTH_ACCESS_TOKEN&oauth_signature_method=PLAINTEXT&oauth_signature=$APPSECRET%26$OAUTH_ACCESS_TOKEN_SECRET&oauth_timestamp=$(utime)&oauth_nonce=$RANDOM" "$API_INFO_URL" 2> /dev/null check_http_response #Check if grep -q "^HTTP/1.1 200 OK" "$RESPONSE_FILE"; then quota=$(sed -n 's/.*"quota": \([0-9]*\).*/\1/p' "$RESPONSE_FILE") used=$(sed -n 's/.*"normal": \([0-9]*\).*/\1/p' "$RESPONSE_FILE") let free_quota=$quota-$used echo $free_quota else echo 0 fi}#Generic download wrapper#$1 = Remote source file/dir#$2 = Local destination file/dirfunction db_download{ local SRC=$(normalize_path "$1") local DST=$(normalize_path "$2") TYPE=$(db_stat "$SRC") #It's a directory if [[ $TYPE == "DIR" ]]; then #If the DST folder is not specified, I assume that is the current directory if [[ $DST == "" ]]; then DST="." fi #Checking if the destination directory exists if [[ ! -d $DST ]]; then local basedir="" else local basedir=$(basename "$SRC") fi local DEST_DIR=$(normalize_path "$DST/$basedir") print " > Downloading \"$SRC\" to \"$DEST_DIR\"... \n" print " > Creating local directory \"$DEST_DIR\"... " mkdir -p "$DEST_DIR" #Check if [[ $? == 0 ]]; then print "DONE\n" else print "FAILED\n" ERROR_STATUS=1 return fi #Extracting directory content [...] #and replacing "}, {" with "}\n{" #I don't like this piece of code... but seems to be the only way to do this with SED, writing a portable code... local DIR_CONTENT=$(sed -n 's/.*: \[{\(.*\)/\1/p' "$RESPONSE_FILE" | sed 's/}, *{/}\{/g') #Extracting files and subfolders TMP_DIR_CONTENT_FILE="${RESPONSE_FILE}_$RANDOM" echo "$DIR_CONTENT" | sed -n 's/.*"path": *"\([^"]*\)",.*"is_dir": *\([^"]*\),.*/\1:\2/p' > $TMP_DIR_CONTENT_FILE #For each entry... while read -r line; do local FILE=${line%:*} local TYPE=${line#*:} #Removing unneeded / FILE=${FILE##*/} if [[ $TYPE == "false" ]]; then db_download_file "$SRC/$FILE" "$DEST_DIR/$FILE" else db_download "$SRC/$FILE" "$DEST_DIR" fi done < $TMP_DIR_CONTENT_FILE rm -fr $TMP_DIR_CONTENT_FILE #It's a file elif [[ $TYPE == "FILE" ]]; then #Checking DST if [[ $DST == "" ]]; then DST=$(basename "$SRC") fi #If the destination is a directory, the file will be download into if [[ -d $DST ]]; then DST="$DST/$SRC" fi db_download_file "$SRC" "$DST" #Doesn't exists else print " > No such file or directory: $SRC\n" ERROR_STATUS=1 return fi}#Simple file download#$1 = Remote source file#$2 = Local destination filefunction db_download_file{ local FILE_SRC=$(normalize_path "$1") local FILE_DST=$(normalize_path "$2") if [[ $SHOW_PROGRESSBAR == 1 && $QUIET == 0 ]]; then CURL_PARAMETERS="--progress-bar" LINE_CR="\n" else CURL_PARAMETERS="-s" LINE_CR="" fi #Checking if the file already exists if [[ -e $FILE_DST && $SKIP_EXISTING_FILES == 1 ]]; then print " > Skipping already existing file \"$FILE_DST\"\n" return fi #Creating the empty file, that for two reasons: #1) In this way I can check if the destination file is writable or not #2) Curl doesn't automatically creates files with 0 bytes size dd if=/dev/zero of="$FILE_DST" count=0 2> /dev/null if [[ $? != 0 ]]; then print " > Error writing file $FILE_DST: permission denied\n" ERROR_STATUS=1 return fi print " > Downloading \"$FILE_SRC\" to \"$FILE_DST\"... $LINE_CR" $CURL_BIN $CURL_ACCEPT_CERTIFICATES $CURL_PARAMETERS --globoff -D "$RESPONSE_FILE" -o "$FILE_DST" "$API_DOWNLOAD_URL/$ACCESS_LEVEL/$(urlencode "$FILE_SRC")?oauth_consumer_key=$APPKEY&oauth_token=$OAUTH_ACCESS_TOKEN&oauth_signature_method=PLAINTEXT&oauth_signature=$APPSECRET%26$OAUTH_ACCESS_TOKEN_SECRET&oauth_timestamp=$(utime)&oauth_nonce=$RANDOM" check_http_response #Check if grep -q "^HTTP/1.1 200 OK" "$RESPONSE_FILE"; then print "DONE\n" else print "FAILED\n" rm -fr "$FILE_DST" ERROR_STATUS=1 return fi}#Prints account infofunction db_account_info{ print "Dropbox Uploader v$VERSION\n\n" print " > Getting info... " $CURL_BIN $CURL_ACCEPT_CERTIFICATES -s --show-error --globoff -i -o "$RESPONSE_FILE" --data "oauth_consumer_key=$APPKEY&oauth_token=$OAUTH_ACCESS_TOKEN&oauth_signature_method=PLAINTEXT&oauth_signature=$APPSECRET%26$OAUTH_ACCESS_TOKEN_SECRET&oauth_timestamp=$(utime)&oauth_nonce=$RANDOM" "$API_INFO_URL" 2> /dev/null check_http_response #Check if grep -q "^HTTP/1.1 200 OK" "$RESPONSE_FILE"; then name=$(sed -n 's/.*"display_name": "\([^"]*\).*/\1/p' "$RESPONSE_FILE") echo -e "\n\nName:\t$name" uid=$(sed -n 's/.*"uid": \([0-9]*\).*/\1/p' "$RESPONSE_FILE") echo -e "UID:\t$uid" email=$(sed -n 's/.*"email": "\([^"]*\).*/\1/p' "$RESPONSE_FILE") echo -e "Email:\t$email" quota=$(sed -n 's/.*"quota": \([0-9]*\).*/\1/p' "$RESPONSE_FILE") let quota_mb=$quota/1024/1024 echo -e "Quota:\t$quota_mb Mb" used=$(sed -n 's/.*"normal": \([0-9]*\).*/\1/p' "$RESPONSE_FILE") let used_mb=$used/1024/1024 echo -e "Used:\t$used_mb Mb" let free_mb=($quota-$used)/1024/1024 echo -e "Free:\t$free_mb Mb" echo "" else print "FAILED\n" ERROR_STATUS=1 fi}#Account unlinkfunction db_unlink{ echo -ne "Are you sure you want unlink this script from your Dropbox account? [y/n]" read answer if [[ $answer == "y" ]]; then rm -fr "$CONFIG_FILE" echo -ne "DONE\n" fi}#Delete a remote file#$1 = Remote file to deletefunction db_delete{ local FILE_DST=$(normalize_path "$1") print " > Deleting \"$FILE_DST\"... " $CURL_BIN $CURL_ACCEPT_CERTIFICATES -s --show-error --globoff -i -o "$RESPONSE_FILE" --data "oauth_consumer_key=$APPKEY&oauth_token=$OAUTH_ACCESS_TOKEN&oauth_signature_method=PLAINTEXT&oauth_signature=$APPSECRET%26$OAUTH_ACCESS_TOKEN_SECRET&oauth_timestamp=$(utime)&oauth_nonce=$RANDOM&root=$ACCESS_LEVEL&path=$(urlencode "$FILE_DST")" "$API_DELETE_URL" 2> /dev/null check_http_response #Check if grep -q "^HTTP/1.1 200 OK" "$RESPONSE_FILE"; then print "DONE\n" else print "FAILED\n" ERROR_STATUS=1 fi}#Move/Rename a remote file#$1 = Remote file to rename or move#$2 = New file name or locationfunction db_move{ local FILE_SRC=$(normalize_path "$1") local FILE_DST=$(normalize_path "$2") TYPE=$(db_stat "$FILE_DST") #If the destination it's a directory, the source will be moved into it if [[ $TYPE == "DIR" ]]; then local filename=$(basename "$FILE_SRC") FILE_DST=$(normalize_path "$FILE_DST/$filename") fi print " > Moving \"$FILE_SRC\" to \"$FILE_DST\" ... " $CURL_BIN $CURL_ACCEPT_CERTIFICATES -s --show-error --globoff -i -o "$RESPONSE_FILE" --data "oauth_consumer_key=$APPKEY&oauth_token=$OAUTH_ACCESS_TOKEN&oauth_signature_method=PLAINTEXT&oauth_signature=$APPSECRET%26$OAUTH_ACCESS_TOKEN_SECRET&oauth_timestamp=$(utime)&oauth_nonce=$RANDOM&root=$ACCESS_LEVEL&from_path=$(urlencode "$FILE_SRC")&to_path=$(urlencode "$FILE_DST")" "$API_MOVE_URL" 2> /dev/null check_http_response #Check if grep -q "^HTTP/1.1 200 OK" "$RESPONSE_FILE"; then print "DONE\n" else print "FAILED\n" ERROR_STATUS=1 fi}#Copy a remote file to a remote location#$1 = Remote file to rename or move#$2 = New file name or locationfunction db_copy{ local FILE_SRC=$(normalize_path "$1") local FILE_DST=$(normalize_path "$2") TYPE=$(db_stat "$FILE_DST") #If the destination it's a directory, the source will be copied into it if [[ $TYPE == "DIR" ]]; then local filename=$(basename "$FILE_SRC") FILE_DST=$(normalize_path "$FILE_DST/$filename") fi print " > Copying \"$FILE_SRC\" to \"$FILE_DST\" ... " $CURL_BIN $CURL_ACCEPT_CERTIFICATES -s --show-error --globoff -i -o "$RESPONSE_FILE" --data "oauth_consumer_key=$APPKEY&oauth_token=$OAUTH_ACCESS_TOKEN&oauth_signature_method=PLAINTEXT&oauth_signature=$APPSECRET%26$OAUTH_ACCESS_TOKEN_SECRET&oauth_timestamp=$(utime)&oauth_nonce=$RANDOM&root=$ACCESS_LEVEL&from_path=$(urlencode "$FILE_SRC")&to_path=$(urlencode "$FILE_DST")" "$API_COPY_URL" 2> /dev/null check_http_response #Check if grep -q "^HTTP/1.1 200 OK" "$RESPONSE_FILE"; then print "DONE\n" else print "FAILED\n" ERROR_STATUS=1 fi}#Create a new directory#$1 = Remote directory to createfunction db_mkdir{ local DIR_DST=$(normalize_path "$1") print " > Creating Directory \"$DIR_DST\"... " $CURL_BIN $CURL_ACCEPT_CERTIFICATES -s --show-error --globoff -i -o "$RESPONSE_FILE" --data "oauth_consumer_key=$APPKEY&oauth_token=$OAUTH_ACCESS_TOKEN&oauth_signature_method=PLAINTEXT&oauth_signature=$APPSECRET%26$OAUTH_ACCESS_TOKEN_SECRET&oauth_timestamp=$(utime)&oauth_nonce=$RANDOM&root=$ACCESS_LEVEL&path=$(urlencode "$DIR_DST")" "$API_MKDIR_URL" 2> /dev/null check_http_response #Check if grep -q "^HTTP/1.1 200 OK" "$RESPONSE_FILE"; then print "DONE\n" elif grep -q "^HTTP/1.1 403 Forbidden" "$RESPONSE_FILE"; then print "ALREADY EXISTS\n" else print "FAILED\n" ERROR_STATUS=1 fi}#List remote directory#$1 = Remote directoryfunction db_list{ local DIR_DST=$(normalize_path "$1") print " > Listing \"$DIR_DST\"... " $CURL_BIN $CURL_ACCEPT_CERTIFICATES -s --show-error --globoff -i -o "$RESPONSE_FILE" "$API_METADATA_URL/$ACCESS_LEVEL/$(urlencode "$DIR_DST")?oauth_consumer_key=$APPKEY&oauth_token=$OAUTH_ACCESS_TOKEN&oauth_signature_method=PLAINTEXT&oauth_signature=$APPSECRET%26$OAUTH_ACCESS_TOKEN_SECRET&oauth_timestamp=$(utime)&oauth_nonce=$RANDOM" 2> /dev/null check_http_response #Check if grep -q "^HTTP/1.1 200 OK" "$RESPONSE_FILE"; then local IS_DIR=$(sed -n 's/^\(.*\)\"contents":.\[.*/\1/p' "$RESPONSE_FILE") #It's a directory if [[ $IS_DIR != "" ]]; then print "DONE\n" #Extracting directory content [...] #and replacing "}, {" with "}\n{" #I don't like this piece of code... but seems to be the only way to do this with SED, writing a portable code... local DIR_CONTENT=$(sed -n 's/.*: \[{\(.*\)/\1/p' "$RESPONSE_FILE" | sed 's/}, *{/}\{/g') #Converting escaped quotes to unicode format echo "$DIR_CONTENT" | sed 's/\\"/\\u0022/' > "$TEMP_FILE" #Extracting files and subfolders rm -fr "$RESPONSE_FILE" while read -r line; do local FILE=$(echo "$line" | sed -n 's/.*"path": *"\([^"]*\)".*/\1/p') local IS_DIR=$(echo "$line" | sed -n 's/.*"is_dir": *\([^,]*\).*/\1/p') local SIZE=$(echo "$line" | sed -n 's/.*"bytes": *\([0-9]*\).*/\1/p') echo -e "$FILE:$IS_DIR;$SIZE" >> "$RESPONSE_FILE" done < "$TEMP_FILE" #Looking for the biggest file size #to calculate the padding to use local padding=0 while read -r line; do local FILE=${line%:*} local META=${line##*:} local SIZE=${META#*;} if [[ ${#SIZE} -gt $padding ]]; then padding=${#SIZE} fi done < "$RESPONSE_FILE" #For each entry, printing directories... while read -r line; do local FILE=${line%:*} local META=${line##*:} local TYPE=${META%;*} local SIZE=${META#*;} #Removing unneeded / FILE=${FILE##*/} if [[ $TYPE != "false" ]]; then FILE=$(echo -e "$FILE") $PRINTF " [D] %-${padding}s %s\n" "$SIZE" "$FILE" fi done < "$RESPONSE_FILE" #For each entry, printing files... while read -r line; do local FILE=${line%:*} local META=${line##*:} local TYPE=${META%;*} local SIZE=${META#*;} #Removing unneeded / FILE=${FILE##*/} if [[ $TYPE == "false" ]]; then FILE=$(echo -e "$FILE") $PRINTF " [F] %-${padding}s %s\n" "$SIZE" "$FILE" fi done < "$RESPONSE_FILE" #It's a file else print "FAILED: $DIR_DST is not a directory!\n" ERROR_STATUS=1 fi else print "FAILED\n" ERROR_STATUS=1 fi}#Share remote file#$1 = Remote filefunction db_share{ local FILE_DST=$(normalize_path "$1") $CURL_BIN $CURL_ACCEPT_CERTIFICATES -s --show-error --globoff -i -o "$RESPONSE_FILE" "$API_SHARES_URL/$ACCESS_LEVEL/$(urlencode "$FILE_DST")?oauth_consumer_key=$APPKEY&oauth_token=$OAUTH_ACCESS_TOKEN&oauth_signature_method=PLAINTEXT&oauth_signature=$APPSECRET%26$OAUTH_ACCESS_TOKEN_SECRET&oauth_timestamp=$(utime)&oauth_nonce=$RANDOM&short_url=false" 2> /dev/null check_http_response #Check if grep -q "^HTTP/1.1 200 OK" "$RESPONSE_FILE"; then print " > Share link: " echo $(sed -n 's/.*"url": "\([^"]*\).*/\1/p' "$RESPONSE_FILE") else print "FAILED\n" ERROR_STATUS=1 fi}#################### SETUP #####################CHECKING FOR AUTH FILEif [[ -e $CONFIG_FILE ]]; then #Loading data... and change old format config if necesary. source "$CONFIG_FILE" 2>/dev/null || { sed -i'' 's/:/=/' "$CONFIG_FILE" && source "$CONFIG_FILE" 2>/dev/null } #Checking the loaded data if [[ $APPKEY == "" || $APPSECRET == "" || $OAUTH_ACCESS_TOKEN_SECRET == "" || $OAUTH_ACCESS_TOKEN == "" ]]; then echo -ne "Error loading data from $CONFIG_FILE...\n" echo -ne "It is recommended to run $0 unlink\n" remove_temp_files exit 1 fi #Back compatibility with previous Dropbox Uploader versions if [[ $ACCESS_LEVEL == "" ]]; then ACCESS_LEVEL="dropbox" fi#NEW SETUP...else echo -ne "\n This is the first time you run this script.\n\n" echo -ne " 1) Open the following URL in your Browser, and log in using your account: $APP_CREATE_URL\n" echo -ne " 2) Click on \"Create App\", then select \"Dropbox API app\"\n" echo -ne " 3) Select \"Files and datastores\"\n" echo -ne " 4) Now go on with the configuration, choosing the app permissions and access restrictions to your DropBox folder\n" echo -ne " 5) Enter the \"App Name\" that you prefer (e.g. MyUploader$RANDOM$RANDOM$RANDOM)\n\n" echo -ne " Now, click on the \"Create App\" button.\n\n" echo -ne " When your new App is successfully created, please type the\n" echo -ne " App Key, App Secret and the Permission type shown in the confirmation page:\n\n" #Getting the app key and secret from the user while (true); do echo -n " # App key: " read APPKEY echo -n " # App secret: " read APPSECRET echo -n " # Permission type, App folder or Full Dropbox [a/f]: " read ACCESS_LEVEL if [[ $ACCESS_LEVEL == "a" ]]; then ACCESS_LEVEL="sandbox" ACCESS_MSG="App Folder" else ACCESS_LEVEL="dropbox" ACCESS_MSG="Full Dropbox" fi echo -ne "\n > App key is $APPKEY, App secret is $APPSECRET and Access level is $ACCESS_MSG. Looks ok? [y/n]: " read answer if [[ $answer == "y" ]]; then break; fi done #TOKEN REQUESTS echo -ne "\n > Token request... " $CURL_BIN $CURL_ACCEPT_CERTIFICATES -s --show-error --globoff -i -o "$RESPONSE_FILE" --data "oauth_consumer_key=$APPKEY&oauth_signature_method=PLAINTEXT&oauth_signature=$APPSECRET%26&oauth_timestamp=$(utime)&oauth_nonce=$RANDOM" "$API_REQUEST_TOKEN_URL" 2> /dev/null check_http_response OAUTH_TOKEN_SECRET=$(sed -n 's/oauth_token_secret=\([a-z A-Z 0-9]*\).*/\1/p' "$RESPONSE_FILE") OAUTH_TOKEN=$(sed -n 's/.*oauth_token=\([a-z A-Z 0-9]*\)/\1/p' "$RESPONSE_FILE") if [[ $OAUTH_TOKEN != "" && $OAUTH_TOKEN_SECRET != "" ]]; then echo -ne "OK\n" else echo -ne " FAILED\n\n Please, check your App key and secret...\n\n" remove_temp_files exit 1 fi while (true); do #USER AUTH echo -ne "\n Please open the following URL in your browser, and allow Dropbox Uploader\n" echo -ne " to access your DropBox folder:\n\n --> ${API_USER_AUTH_URL}?oauth_token=$OAUTH_TOKEN\n" echo -ne "\nPress enter when done...\n" read #API_ACCESS_TOKEN_URL echo -ne " > Access Token request... " $CURL_BIN $CURL_ACCEPT_CERTIFICATES -s --show-error --globoff -i -o "$RESPONSE_FILE" --data "oauth_consumer_key=$APPKEY&oauth_token=$OAUTH_TOKEN&oauth_signature_method=PLAINTEXT&oauth_signature=$APPSECRET%26$OAUTH_TOKEN_SECRET&oauth_timestamp=$(utime)&oauth_nonce=$RANDOM" "$API_ACCESS_TOKEN_URL" 2> /dev/null check_http_response OAUTH_ACCESS_TOKEN_SECRET=$(sed -n 's/oauth_token_secret=\([a-z A-Z 0-9]*\)&.*/\1/p' "$RESPONSE_FILE") OAUTH_ACCESS_TOKEN=$(sed -n 's/.*oauth_token=\([a-z A-Z 0-9]*\)&.*/\1/p' "$RESPONSE_FILE") OAUTH_ACCESS_UID=$(sed -n 's/.*uid=\([0-9]*\)/\1/p' "$RESPONSE_FILE") if [[ $OAUTH_ACCESS_TOKEN != "" && $OAUTH_ACCESS_TOKEN_SECRET != "" && $OAUTH_ACCESS_UID != "" ]]; then echo -ne "OK\n" #Saving data in new format, compatible with source command. echo "APPKEY=$APPKEY" > "$CONFIG_FILE" echo "APPSECRET=$APPSECRET" >> "$CONFIG_FILE" echo "ACCESS_LEVEL=$ACCESS_LEVEL" >> "$CONFIG_FILE" echo "OAUTH_ACCESS_TOKEN=$OAUTH_ACCESS_TOKEN" >> "$CONFIG_FILE" echo "OAUTH_ACCESS_TOKEN_SECRET=$OAUTH_ACCESS_TOKEN_SECRET" >> "$CONFIG_FILE" echo -ne "\n Setup completed!\n" break else print " FAILED\n" ERROR_STATUS=1 fi done; remove_temp_files exit $ERROR_STATUSfi#################### START ####################COMMAND=${@:$OPTIND:1}ARG1=${@:$OPTIND+1:1}ARG2=${@:$OPTIND+2:1}let argnum=$#-$OPTIND#CHECKING PARAMS VALUEScase $COMMAND in upload) if [[ $argnum -lt 2 ]]; then usage fi FILE_DST=${@:$#:1} for (( i=$OPTIND+1; i<$#; i++ )); do FILE_SRC=${@:$i:1} db_upload "$FILE_SRC" "/$FILE_DST" done ;; download) if [[ $argnum -lt 1 ]]; then usage fi FILE_SRC=$ARG1 FILE_DST=$ARG2 db_download "/$FILE_SRC" "$FILE_DST" ;; share) if [[ $argnum -lt 1 ]]; then usage fi FILE_DST=$ARG1 db_share "/$FILE_DST" ;; info) db_account_info ;; delete|remove) if [[ $argnum -lt 1 ]]; then usage fi FILE_DST=$ARG1 db_delete "/$FILE_DST" ;; move|rename) if [[ $argnum -lt 2 ]]; then usage fi FILE_SRC=$ARG1 FILE_DST=$ARG2 db_move "/$FILE_SRC" "/$FILE_DST" ;; copy) if [[ $argnum -lt 2 ]]; then usage fi FILE_SRC=$ARG1 FILE_DST=$ARG2 db_copy "/$FILE_SRC" "/$FILE_DST" ;; mkdir) if [[ $argnum -lt 1 ]]; then usage fi DIR_DST=$ARG1 db_mkdir "/$DIR_DST" ;; list) DIR_DST=$ARG1 #Checking DIR_DST if [[ $DIR_DST == "" ]]; then DIR_DST="/" fi db_list "/$DIR_DST" ;; unlink) db_unlink ;; *) if [[ $COMMAND != "" ]]; then print "Error: Unknown command: $COMMAND\n\n" ERROR_STATUS=1 fi usage ;;esacremove_temp_filesexit $ERROR_STATUS
到此,相信大家对"如何编写shell脚本将VPS上的数据备份到Dropbox网盘"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
备份
数据
数据备份
脚本
内容
学习
实用
更深
兴趣
实用性
实际
操作简单
方法
更多
朋友
网站
频道
e.g.
查询
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
生物智慧铸牢网络安全
数据库工具
云服务器怎么搭建代理ip
苹果手机连接到服务器时出现问题
数据库视图存在哪儿
网络安全设施设备表
胡杨网络技术有限公司
查看本地域名服务器的缓存
营口新世纪软件开发有限公司
Z2计算机网络技术
环保币网络安全性
行列倒置数据库
数据库怎么设置在网页上
网络安全自查检查工作总结
崇明区创新数据库服务销售
旌德软件开发项目管理在线咨询
火山安卓软件开发平台怎样用
网络技术与应用考试题型
网络安全宣传手操报
昆明西湖棋牌平台软件开发
联通号码存在风险网络安全法
系统网络安全对国家的好处
多程序同时查询数据库慢
数据库的最终存储形式是什么
erp需要服务器吗
订单 数据库设计
汽车电子软件开发与测试论坛
2021网络安全寄语
财务数据放公司服务器安全吗
网络安全宣传手操报