我的编程空间,编程开发者的网络收藏夹
学习永远不晚

如何编写shell脚本将VPS上的数据备份到Dropbox网盘

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

如何编写shell脚本将VPS上的数据备份到Dropbox网盘

本篇内容主要讲解“如何编写shell脚本将VPS上的数据备份到Dropbox网盘”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何编写shell脚本将VPS上的数据备份到Dropbox网盘”吧!

#!/usr/bin/env bash## Dropbox Uploader## Copyright (C) 2010-2014 Andrea Fabrizi <andrea.fabrizi@gmail.com>## 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  <LOCAL_FILE/DIR ...> <REMOTE_FILE/DIR>"  echo -e "\t download <REMOTE_FILE/DIR> [LOCAL_FILE/DIR]"  echo -e "\t delete  <REMOTE_FILE/DIR>"  echo -e "\t move   <REMOTE_FILE/DIR> <REMOTE_FILE/DIR>"  echo -e "\t copy   <REMOTE_FILE/DIR> <REMOTE_FILE/DIR>"  echo -e "\t mkdir  <REMOTE_DIR>"  echo -e "\t list   [REMOTE_DIR]"  echo -e "\t share  <REMOTE_FILE>"  echo -e "\t info"  echo -e "\t unlink"  echo -e "\nOptional parameters:"  echo -e "\t-f <FILENAME> 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<strlen ; pos++ )); do    c=${string:$pos:1}    case "$c" in      [-_.~a-zA-Z0-9] ) o="${c}" ;;      * ) $PRINTF $PRINTF_OPT '%%%02x' "'$c"    esac    encoded+="${o}"  done  echo "$encoded"}function normalize_path{  path=$(echo -e "$1")  if [[ $HAVE_READLINK == 1 ]]; then    readlink -m "$path"  else    echo "$path"  fi}#Check if it's a file or directory#Returns FILE/DIR/ERRfunction db_stat{  local FILE=$(normalize_path "$1")  #Checking if it's a file or a directory  $CURL_BIN $CURL_ACCEPT_CERTIFICATES -s --show-error --globoff -i -o "$RESPONSE_FILE" "$API_METADATA_URL/$ACCESS_LEVEL/$(urlencode "$FILE")?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  #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 class="lazy" data-src=$(normalize_path "$1")  local DST=$(normalize_path "$2")  #Checking if the file/dir exists  if [[ ! -e $class="lazy" data-src && ! -d $class="lazy" data-src ]]; then    print " > No such file or directory: $class="lazy" data-src\n"    ERROR_STATUS=1    return  fi  #Checking if the file/dir has read permissions  if [[ ! -r $class="lazy" data-src ]]; then    print " > Error reading file $class="lazy" data-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 "$class="lazy" data-src")    DST="$DST/$filename"  fi  #It's a directory  if [[ -d $class="lazy" data-src ]]; then    db_upload_dir "$class="lazy" data-src" "$DST"  #It's a file  elif [[ -e $class="lazy" data-src ]]; then    db_upload_file "$class="lazy" data-src" "$DST"  #Unsupported object...  else    print " > Skipping not regular file \"$class="lazy" data-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_class="lazy" data-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_class="lazy" data-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_class="lazy" data-src" "$FILE_DST"  else    db_simple_upload_file "$FILE_class="lazy" data-src" "$FILE_DST"  fi}#Simple file upload#$1 = Local source file#$2 = Remote destination filefunction db_simple_upload_file{  local FILE_class="lazy" data-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_class="lazy" data-src\" to \"$FILE_DST\"... $LINE_CR"  $CURL_BIN $CURL_ACCEPT_CERTIFICATES $CURL_PARAMETERS -i --globoff -o "$RESPONSE_FILE" --upload-file "$FILE_class="lazy" data-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_class="lazy" data-src=$(normalize_path "$1")  local FILE_DST=$(normalize_path "$2")  print " > Uploading \"$FILE_class="lazy" data-src\" to \"$FILE_DST\""  local FILE_SIZE=$(file_size "$FILE_class="lazy" data-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_class="lazy" data-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_class="lazy" data-src=$(normalize_path "$1")  local DIR_DST=$(normalize_path "$2")  #Creatig remote directory  db_mkdir "$DIR_DST"  for file in "$DIR_class="lazy" data-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 class="lazy" data-src=$(normalize_path "$1")  local DST=$(normalize_path "$2")  TYPE=$(db_stat "$class="lazy" data-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 "$class="lazy" data-src")    fi    local DEST_DIR=$(normalize_path "$DST/$basedir")    print " > Downloading \"$class="lazy" data-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 "$class="lazy" data-src/$FILE" "$DEST_DIR/$FILE"      else        db_download "$class="lazy" data-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 "$class="lazy" data-src")    fi    #If the destination is a directory, the file will be download into    if [[ -d $DST ]]; then      DST="$DST/$class="lazy" data-src"    fi    db_download_file "$class="lazy" data-src" "$DST"  #Doesn't exists  else    print " > No such file or directory: $class="lazy" data-src\n"    ERROR_STATUS=1    return  fi}#Simple file download#$1 = Remote source file#$2 = Local destination filefunction db_download_file{  local FILE_class="lazy" data-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_class="lazy" data-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_class="lazy" data-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_class="lazy" data-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_class="lazy" data-src")    FILE_DST=$(normalize_path "$FILE_DST/$filename")  fi  print " > Moving \"$FILE_class="lazy" data-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_class="lazy" data-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_class="lazy" data-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_class="lazy" data-src")    FILE_DST=$(normalize_path "$FILE_DST/$filename")  fi  print " > Copying \"$FILE_class="lazy" data-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_class="lazy" data-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_class="lazy" data-src=${@:$i:1}      db_upload "$FILE_class="lazy" data-src" "/$FILE_DST"    done  ;;  download)    if [[ $argnum -lt 1 ]]; then      usage    fi    FILE_class="lazy" data-src=$ARG1    FILE_DST=$ARG2    db_download "/$FILE_class="lazy" data-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_class="lazy" data-src=$ARG1    FILE_DST=$ARG2    db_move "/$FILE_class="lazy" data-src" "/$FILE_DST"  ;;  copy)    if [[ $argnum -lt 2 ]]; then      usage    fi    FILE_class="lazy" data-src=$ARG1    FILE_DST=$ARG2    db_copy "/$FILE_class="lazy" data-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网盘”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

如何编写shell脚本将VPS上的数据备份到Dropbox网盘

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

如何编写shell脚本将VPS上的数据备份到Dropbox网盘

本篇内容主要讲解“如何编写shell脚本将VPS上的数据备份到Dropbox网盘”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何编写shell脚本将VPS上的数据备份到Dropbox网盘”吧!
2023-06-09

编写shell脚本将VPS上的数据备份到Dropbox网盘的方法

看到有人用dropbox备份网站数据,所以今天也试了一下,记得以前是一个python脚本,这是用的是bash 脚本,利用dropbox的api来上传下载的,很方便,脚本的地址是Dropbox-Uploader/dropbox_uploade
2022-06-04

如何进行Linux VPS下备份网站数据到ftp的一键脚本

如何进行Linux VPS下备份网站数据到ftp的一键脚本,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。代码如下:#! /bin/bashcd /home/www/deepvp
2023-06-10

如何编写linux数据库备份并通过ftp上传脚本

本篇内容介绍了“如何编写linux数据库备份并通过ftp上传脚本”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!代码如下:#!/bin/bas
2023-06-09

CentOS中如何使用Shell脚本实现每天自动备份网站文件和数据库并上传到FTP中

这篇文章主要讲解了“CentOS中如何使用Shell脚本实现每天自动备份网站文件和数据库并上传到FTP中”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“CentOS中如何使用Shell脚本实现
2023-06-09

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录