一、paramiko簡介
1.paramiko是一個基于SSHv2協議的純Python庫。需要單獨安裝。
2.它提供了客戶端和服務器的功能。
3.可以實現SSH2遠程安全連接,支持用戶名、密碼連接,也支持密鑰連接
4.一般用于執行遠程命令、傳輸文件、中間SSH代理等
安裝
pip3 install paramiko
在linux中安裝過程報錯:
Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-build-obpexfgv/bcrypt/
解決:
pip3 install --upgrade pip3 setuptools
二、SSH連接
1.基于用戶名和密碼的連接
import paramikocommand = "cat /etc/passwd |awk -F: '{print $1}'|head"# 要連接的主機的信息,以下是必填項
host_info = {"hostname": "192.168.1.23","port": 22,"username": "root","password": "服務器密碼"
}def ssh_host(hostinfo):# 實例化一個SSHClient 對象,用于連接linux服務器使用ssh_client = paramiko.SSHClient()# 當使用用戶名和密碼首次連接linux服務器時會有連接提示,也是輸入yes/no的提示。這里的設置就是會自動輸入yesssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy)try:# 開始連接目標linux服務器ssh_client.connect(**host_info)except Exception:print(f"連接{host_info['hostname']}失敗")else:# 遠程執行shell命令stdin,stdout,stderr = ssh_client.exec_command(command)# 這里decode的作用 1是解碼 2是格式化print(stdout.read().decode())# 判斷執行命令是否有報錯,如果有報錯就打印if not stderr is None:print(stderr.read().decode())ssh_client.close()if __name__ == "__main__":ssh_host(host_info)
執行結果如下:
root
bin
daemon
adm
lp
sync
shutdown
halt
mail
operator
2.基于密鑰的連接
import paramiko
command = "awk -F: '{print $1}' /etc/passwd"# 讀取私鑰文件
private_key = paramiko.RSAKey.from_private_key_file('/root/.ssh/id_rsa')host_info = {"hostname": "192.168.1.106","port": 22,"username": "root",# 這里就是傳遞私鑰文件"pkey": private_key
}def main(host_info):ssh_client = paramiko.SSHClient()ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())try:ssh_client.connect(**host_info)except Exception:print(f"連接{host_info['hostname']}失敗")else:stdin, stdout, stderr = ssh_client.exec_command(command)# 這里decode的作用 1是解碼 2是格式化print(stdout.read().decode())# 判斷執行命令是否有報錯,如果有報錯就打印if not stderr is None:print(stderr.read().decode())ssh_client.close()if __name__ == '__main__':main(host_info)
三、遠程文件操作
1.STPClient類簡介
SFTPClient作為一個SFTP客戶端對象,根據SSH傳輸協議的sftp會話,實現遠程操作,比如文件上傳,下載,權限,狀態等,端口就是SSH端口
方法 | 含義 |
---|---|
from_transport() | 創建一個已連通的SFTP客戶端通道 |
put() | 上傳本地文件到遠程服務器 |
get() | 從遠程服務器下載文件到本地 |
mkdir() | 在遠程服務器上創建目錄 |
remove() | 刪除遠程服務器中的文件 |
rmdir() | 刪除遠程服務器中的目錄 |
rename() | 重命名遠程服務器中的文件或目錄 |
stat() | 獲取遠程服務器中文件的詳細信息 |
listdir() | 列出遠程服務器中指定目錄下的內容 |
2.代碼實例:
import paramikohost_addr = ('192.168.1.23',22
)
user_info = {"username": "root","password": "666666"}
def sftp_host():tran = paramiko.Transport(*host_addr)tran.connect(**user_info)sftp_client = paramiko.SFTPClient.from_transport(tran)local_path = "D:/服務臨時交付文件/zabbix_agent-6.0.3-linux-4.12-ppc64le-static.tar.gz"remote_path = "/root/zabbix_agent-6.0.3-linux-4.12-ppc64le-static.tar.gz"# 上傳文件(下發文件)sftp_client.put(local_path,remote_path)# 下載文件sftp_client.get(remote_path,local_path)tran.close()if __name__ == "__main__":sftp_host()
四、django的文件上傳
1.前端代碼
準備工作
1.安裝node
2.使用npm 安裝pnpm工具
這里使用前端代碼做測試的原因:
1.原生html input type=file 太丑了
2.必須在input type=file中加入enctype="multipart/form-data"屬性,此屬性的含義是:規定在發送到服務器之前應該如何對表單數據進行編碼。如果沒有這一行,django的 request.FILES的值是空的。所以在這里使用UI組件進行測試。看看是否也存在request.FILES為空的問題
1.1 配置代理地址
淘寶的地址使用vite創建項目報錯,所以這里重新配置代理
npm config set registry https://registry.npmjs.org/
1.2 使用vite創建vue項目
pnpm create vitecd 項目名稱# 安裝依賴
pnpm install # 啟動項目
pnpm run dev
1.3 安裝UI組件
1.3.1 安裝ant-design-vue
pnpm install ant-design-vue --save
查看安裝的版本
E:\code\project\前端項目\vue_test1\vue_test_project>pnpm list |findstr /i ant
ant-design-vue 4.1.2
1.3.2 安裝icon組件
pnpm install --save @ant-design/icons-vue
1.4 引入UI組件
編輯main.js
import { createApp } from 'vue'
import App from './App.vue'# 引入ant-desgin-vue組件的button按鈕
import { Button } from 'ant-design-vue'const app = createApp(App)# 使用Button按鈕組件
app.use(Button)app.mount('#app')
1.5 測試
在瀏覽器中能夠看到漂亮的按鈕,就說明這里已經成功引用了ant-desgin-vue UI組件了.
<script setup></script><template><div><h1>app.vue</h1><!-- 使用引入的button按鈕 --><a-button type="primary">按鈕</a-button></div>
</template><style scoped></style>
1.6 上傳文件完整代碼
編輯App.vue文件
<template>
<div><a-upload v-model:file-list="fileList" list-type="picture" :max-count="10" multiple="true"action="/upload" name='file' @change="handleChange"><a-button type="primary"><upload-outlined></upload-outlined>上傳文件</a-button></a-upload><a-button type="primary" danger class="ClearBt" @click="clearfileList"><DeleteOutlined />清空列表</a-button>
</div>
</template><script lang="js">
export default {name: "App"
}</script><script lang="js" setup>
import { ref } from 'vue';
import { UploadOutlined,DeleteOutlined } from '@ant-design/icons-vue'
import { message } from 'ant-design-vue';const fileList = ref([
]);function clearfileList(){fileList.value = [];
}function handleChange(info){if (info.file.status == "done"){message.success(`${info.file.name} 上傳成功!`)}if (info.file.status == "error"){message.error(`${info.file.name} 上傳失敗`)}
}
</script><style scoped>
div {position: relative;margin: 0px auto;width: 30%;height: 800px;background: #f5f5f5;border-radius: 20px;
}.ClearBt {position: absolute;top: 0px;left: 111px;
}</style>
參數解釋:
list-type: 顯示圖片
max-count: 限制文件上傳的數量
multiple:允許一次上傳多個文件,而不是一次只允許上傳單個文件
name: 這個參數必須要定義,否則后端無法獲取前端提交的數據
main.js代碼如下
import { createApp } from 'vue'
import App from './App.vue'import { Button,Upload } from 'ant-design-vue'const app = createApp(App)app.use(Button)
app.use(Upload)app.mount('#app')
1.7 編譯前端代碼
pnpm run build
編譯成功后在 項目目錄下生成dist目錄,此目錄下就是編譯成功后的代碼
2.部署前端代碼
搭建nginx,過程省略
2.1 nginx server配置
server {listen 16666;server_name localhost;root /data/wwwroot;location / {index index.html;try_files $uri $uri/ /index.html;}location /upload {proxy_pass http://127.0.0.1:18888/files/upload/;}
}
nginx -s reload
2.2 上傳前端代碼
將編譯好的所有的代碼上傳到/data/wwwroot目錄下。訪問:
http://IP地址:16666
3.部署后端代碼
基礎環境安裝就不在說了
3.1 創建應用
django-admin startapp files
3.2 主路由
編輯項目目錄下的urls.py文件
from django.urls import path,includeurlpatterns = [path('files/',include('files.urls'))
]
3.3 子路由
在files應用下新建urls.py文件
from django.urls import path,include
from .views import *urlpatterns = [path('upload/', file_view.as_view()),
]
3.4 視圖類
from rest_framework.views import APIView
from rest_framework.response import Response
import ossave_url = '/data/pic/'class file_view(APIView):def post(self,request):# 獲取前端上傳的文件,注意這里get的 'file' 一定和前端upload 的name的值對應pic_data = request.FILES.get('file')# 判斷是否能夠獲取到前端傳輸的數據,主要是看前端upload的name值是不是fileif not pic_data is None:pic_name = pic_data.namepicFullUrl = save_url + pic_name# 判斷上傳的文件是否重名if not os.path.exists(picFullUrl):with open(save_url + pic_name,'wb+') as fp:# 這里使用chunks函數,是為分塊處理,為了避免如果文件很大,一次性讀取文件所有,而造成的內存不足現象for chunk in pic_data.chunks():fp.write(chunk)return Response({"message":"文件上傳成功"},status=200)else:# 這里之所有沒有使用鍵值對的形式進行返回,是因為這個異常結果會顯示在圖片的懸浮提示上。return Response("文件已經存在",status=409)else:# 這里之所有沒有使用鍵值對的形式進行返回,是因為這個異常結果會顯示在圖片的懸浮提示上。return Response("文件上傳失敗",status=505)
3.5 啟動項目
python3 manage.py runserver 0.0.0.0:18888
4.訪問測試
訪問頁面,查看圖片是否能夠上傳成功