1. 程式人生 > >如何在客戶端上傳shell指令碼檔案,並利用PHP呼叫執行指令碼

如何在客戶端上傳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中有三種取值
image

如果是檔案上傳,需要將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>

效果如圖:
image
原始的樣子不太好看,為了美觀大家可以使用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>

修改後樣式如圖:
image
-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][name]_FILES[“file”][“type”] - 被上傳檔案的型別
FILES[file][size]_FILES[“file”][“tmp_name”] - 儲存在伺服器的檔案的臨時副本的名稱
$_FILES[“file”][“error”] - 由檔案上傳導致的錯誤程式碼
這是一種非常簡單檔案上傳方式。基於安全方面的考慮,您應當增加有關什麼使用者有權上傳檔案的限制,例如上傳格式和大小。

儲存上傳的檔案到指定資料夾

使用move_uploaded_file(FILES[file][tmpname],storePath.’/’.fileName)moveuploadedfile(file,newloc)chmod(storePath.'/'.$fileName,0755);這個是為了修改上傳檔案的許可權,因為上傳檔案的許可權預設是644,所以如果有執行該檔案的需求則需要自己手動修改許可權;
而標題的第二部分是利用php執行linux命令,shell指令碼函式

PHP執行外部命令的幾個函式

  1. exec()
    string exec ( string command [, array &output [, int &return_var]] )
    說明
    前面是要執行的命令,但是exec執行系統外部命令時不會輸出結果,而是返回結果的最後一行。如果想得到結果,可以使用第二個引數,讓其輸出到指定的陣列。此陣列一個記錄代表輸出的一行。即如果輸出結果有20行,則這個陣列就有20條記錄,所以如果需要反覆輸出呼叫不同系統外部命令的結果,最好在輸出每一條系統外部命令結果時清空這個陣列unset($output),以防混亂。第三個引數用來取得命令執行的狀態碼,通常執行成功都是返回0
  2. shell_exec()
    string shell_exec ( string cmd)