如何在客戶端上傳shell指令碼檔案,並利用PHP呼叫執行指令碼
題目中的上傳包含兩部分,一部分是上傳檔案,一部分是利用PHP執行指令碼
上傳檔案到指定資料夾
所謂檔案上傳是指將本地文字檔案,圖片視訊或者音訊等檔案上傳到伺服器上,以供後續操作的過程。
上傳檔案有幾種方式,包括:
- 單純的form表單上傳提交
使用form表單的input[type=”file”]控制元件,開啟系統的檔案對話選擇框,選擇檔案然後利用submit和form中跳轉的action設定實現上傳。
優點:多瀏覽器相容,簡單
缺點:PHP會限制瀏覽器上傳檔案的大小,而且form表單提交後會重新整理頁面,使用者體驗不好
【注意】
1. input中type要設定成type=”file”;
2. 設定form中method=”post”;
3. form中enctype中有三種取值
如果是檔案上傳,需要將enctype=”multipart/form-data”
如果上傳檔案較大,需要配置php.ini檔案(以上傳500M以下大小的檔案為例)
查詢以下選項並修改->
file_uploads = On ;開啟檔案上傳選項
upload_max_filesize = 500M ;上傳檔案上限
如果要上傳比較大的檔案,僅僅以上兩條還不夠,必須把伺服器快取上限調大,把指令碼最大執行時間變長
post_max_size = 500M ;post上限
max_execution_time = 1800 ; Maximum execution time of each script, in seconds指令碼最大執行時間
max_input_time = 1800 ; Maximum amount of time each script may spend parsing request data
memory_limit = 128M ; Maximum amount of memory a script may consume (128MB)記憶體上限
上程式碼:
<form action="upload_file.php" method="post"
enctype="multipart/form-data">
<input type="file" name="file" id="file" />
<input type="submit" name="submit" id="submit" value="Submit" />
</form>
效果如圖:
原始的樣子不太好看,為了美觀大家可以使用label調整樣式,例如
css部分
.btn {
display: inline-block;
margin-bottom: 0 ;
user-select: none;
}
.btn-info {
padding:8px;
color: #ffffff;
background-color: #40bbea;
border-color: #29b3e7;
}
html部分
<div>
<label for="fileName1" >檔案上傳:</label>
<input type="text" name="fileName1" id="fileName1" style="height: 32px;width: 300px;" />
<label class="btn btn-info" for="updateFile" style="margin-bottom: 3px;">瀏覽</label>
<label class="btn btn-info" style="margin-bottom: 3px;" for="submit" >上傳</label>
<div class="col-xs-12">
<form id= "uploadForm">
<input type="file" id="updateFile" name="file" style="position:absolute;clip:rect(0 0 0 0);">
<input type="text" id="submit" hidden="hidden">
</form>
</div>
</div>
修改後樣式如圖:
-html5的formdata、fileReader
利用FormData模擬表單資料,然後通過ajax提交,用FileReader的readAsDataURL方法拿到base64地址來預覽。
html部分
<div id= "uploadForm">
<input type="text" id="fileName" style="height: 32px;width: 300px;" />
<label class="btn btn-info" for="file" style="margin-bottom: 3px;">
<span>瀏覽</span>
</label>
<label class="btn btn-info" style="margin-bottom: 3px;" for="submit">
<span>上傳</span>
</label>
<input type="file" id="file" name="file" onchange="showPreview(this)" style="position:absolute;clip:rect(0 0 0 0);">
<input type="text" id="submit" onclick="doUpload()" hidden="hidden">
</div>
JavaScript部分
function showPreview(source) {
var arrs = $(source).val().split('\\');
var filename=arrs[arrs.length-1];
$("#fileName").val(filename);
}
function doUpload() {
var formData = new FormData($( "#uploadForm" )[0]); // 要求使用的html物件
$.ajax({
url: 'upload_file.php' ,
type: 'POST',
data: formData,
async: true,
// 下面三個引數要指定,如果不指定,會報一個JQuery的錯誤
cache: false,
contentType: false, //不要設定Content-Type請求頭,因為檔案資料是以 multipart/form-data 來編碼
processData: false,//不處理資料
success: function (returndata) {
/*result = JSON.parse(returndata);*/
alert(returndata);
},
error: function (returndata) {
alert(returndata);
}
});
}
需要注意的部分:
使用jQuery提供的ajax方法來發送二進位制檔案,還需要附加兩個引數:
processData: false // 不要對data引數進行序列化處理,預設為true
contentType: false // 不要設定Content-Type請求頭,因為檔案資料是以 multipart/form-data 來編碼
upload_file.php
<?php
$url=realpath(dirname(__FILE__).'/../../'); //從當前位置退回到www資料夾目錄,這一塊兒可根據自己檔案所在位置做修改
if ($_FILES["file"]["error"] > 0)
{
switch($_FILES["file"]["error"])
{
case 1:
echo "上傳檔案的大小超出了約定值";
break;
case 2:
echo "上傳檔案太大 ";
break;
case 3:
echo "檔案只被部分上傳";
break;
case 4:
echo "沒有上傳任何檔案";
break;
case 6:
echo "未指定臨時目錄";
break;
case 7:
echo "檔案寫入磁碟失敗" ;
break;
}
}
else
{
$storePath = $url. "/upload" ;
// 判斷當期目錄下的 upload 目錄是否存在該檔案
// 如果沒有 upload 目錄,你需要建立它,upload 目錄許可權為 777
if (!file_exists($storePath))
{
mkdir($storePath);
}
else if (file_exists($storePath.'/'.$fileName))
{
echo $fileName . " 檔案已經存在,如需更新,請點選下方'更新系統'按鈕";
}
else
{
//如果 upload 目錄不存在該檔案則將檔案上傳到 upload 目錄下
//判斷檔案上傳是否採用的POST方式
if(is_uploaded_file($_FILES['file']['tmp_name']))
{
if(move_uploaded_file($_FILES['file']['tmp_name'],$storePath.'/'.$fileName))
{
chmod($storePath.'/'.$fileName,0755);//
echo "更新檔案儲存成功,如需更新,請點選下方'更新系統'按鈕";
}else{
echo '更新檔案儲存失敗';
}
}else{
echo '沒有可儲存的更新檔案';
}
}
}
?>
關於PHP上傳檔案
通過使用 PHP 的全域性陣列 $_FILES,你可以從客戶計算機向遠端伺服器上傳檔案。
第一個引數是表單的 input name,第二個下標可以是 “name”, “type”, “size”, “tmp_name” 或 “error”。就像這樣:
_FILES[“file”][“type”] - 被上傳檔案的型別
_FILES[“file”][“tmp_name”] - 儲存在伺服器的檔案的臨時副本的名稱
$_FILES[“file”][“error”] - 由檔案上傳導致的錯誤程式碼
這是一種非常簡單檔案上傳方式。基於安全方面的考慮,您應當增加有關什麼使用者有權上傳檔案的限制,例如上傳格式和大小。
儲存上傳的檔案到指定資料夾
使用move_uploaded_file(storePath.’/’.storePath.'/'.$fileName,0755);這個是為了修改上傳檔案的許可權,因為上傳檔案的許可權預設是644,所以如果有執行該檔案的需求則需要自己手動修改許可權;
而標題的第二部分是利用php執行linux命令,shell指令碼函式
PHP執行外部命令的幾個函式
- exec()
string exec ( string command [, array &output [, int &return_var]] )
說明:
前面是要執行的命令,但是exec執行系統外部命令時不會輸出結果,而是返回結果的最後一行。如果想得到結果,可以使用第二個引數,讓其輸出到指定的陣列。此陣列一個記錄代表輸出的一行。即如果輸出結果有20行,則這個陣列就有20條記錄,所以如果需要反覆輸出呼叫不同系統外部命令的結果,最好在輸出每一條系統外部命令結果時清空這個陣列unset($output),以防混亂。第三個引數用來取得命令執行的狀態碼,通常執行成功都是返回0 - shell_exec()
string shell_exec ( string