當前位置:首頁 » 網頁前端 » java調用rsync腳本方法示例
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

java調用rsync腳本方法示例

發布時間: 2022-12-15 07:07:52

『壹』 怎麼用java代碼調用遠程Linux上的shell腳本

package org.shirdrn.shell;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;

import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.Session;

/**
* 遠程Shell腳本執行工具
*
* @author Administrator
*/
public class RemoteShellTool {

private Connection conn;
private String ipAddr;
private String charset = Charset.defaultCharset().toString();
private String userName;
private String password;

public RemoteShellTool(String ipAddr, String userName, String password, String charset) {
this.ipAddr = ipAddr;
this.userName = userName;
this.password = password;
if(charset != null) {
this.charset = charset;
}
}
/**
* 登錄遠程Linux主機
*
* @return
* @throws IOException
*/
public boolean login() throws IOException {
conn = new Connection(ipAddr);
conn.connect(); // 連接
return conn.authenticateWithPassword(userName, password); // 認證
}

/**
* 執行Shell腳本或命令
*
* @param cmds 命令行序列
* @return
*/
public String exec(String cmds) {
InputStream in = null;
String result = "";
try {
if (this.login()) {
Session session = conn.openSession(); // 打開一個會話
session.execCommand(cmds);
in = session.getStdout();
result = this.processStdout(in, this.charset);
conn.close();
}
} catch (IOException e1) {
e1.printStackTrace();
}
return result;
}

/**
* 解析流獲取字元串信息
*
* @param in 輸入流對象
* @param charset 字元集
* @return
*/
public String processStdout(InputStream in, String charset) {
byte[] buf = new byte[1024];
StringBuffer sb = new StringBuffer();
try {
while (in.read(buf) != -1) {
sb.append(new String(buf, charset));
}
} catch (IOException e) {
e.printStackTrace();
}
return sb.toString();
}
}

『貳』 linux上的rsync命令詳解

rsync 就是遠程同步的意思remote sync.
rsync 被用在UNIX / Linux執行備份操作操作.
rsync 工具包被用來從一個位置到另一個位置高效地同步文件和文件夾. rsync可以實現在同一台機器的不同文件直接備份,也可以跨伺服器備份.

rsync 語法如下

從語法結構我們可以看出, 源和目標即可以在本地也可以在遠端. 如果是遠端的話,需要指明登錄用戶名, 遠端伺服器名, 和遠端文件或目錄. 同時源可以是多個, 目標位置只能是一個.

說明:

-z: --compress 使用壓縮機制

-v: --verbose 列印詳細信息

-r: --recursive 以遞歸模式同步子目錄

注意: 同步完成後, 我們會發現文件的時間戳timestamps發生了改變.

有時我們希望拷貝或同步時, 時間戳不要發生變化, 源文件是什麼時間戳,目標文件就是什麼時間戳, 這時我們需要使用 -a --archive 歸檔模式選項. -a 選項相當於7個選項的組合 -rlptgoD

-r, --recursive: 遞歸模式Recursive mode
-l, --links: 將符號鏈接當作符號鏈接文件拷貝, 不拷貝符合鏈接指向的文件內容.
-p, --perms: 保留文件許可權
-t, --times: 保留修改時間戳
-g, --group: 保留用戶組信息
-o, --owner: 保留用戶信息(需要超級用戶許可權)
-D, 相當於 --devices --specials 的組合, 保留設備文件, 保留特殊文件.

同步完成後, 我們再來看文件屬性, 時間戳信息得到了保留, 不僅如此文件的所有者 和所在組也得到保留.

說明: Pubkeys 是一個普通文件

使用rsync, 也可以從本地拷貝多個文件或目錄到遠端, 以下即為示例:

注意:
與本地文件拷貝不同的地方在於, 當拷貝文件到遠程伺服器時, 我們指定遠程主機上的用戶名, 伺服器地址, 路徑等信息, 類是於使用scp命令拷貝, 如果沒有設置ssh免密碼登錄我們還需要提供遠程用戶的密碼等信息.有時你不想頻繁輸入密碼, 或者rsync運行在一個無人執守的腳本裡面, 這是需要預先設置ssh免密登錄, 或者使用結合expect命令,自動輸入密碼, 但是出於安全考慮, 密碼需要加密. 所以在條件許可的情況下, 還是推薦設置ssh免密登錄.

與示例 4 稍有不同, 這時遠端目錄或文件作為源位置, 本地目錄或文件作為目標位置, 示例如下:

rsync 允許指定遠程主機上運行shell命令.
這時需要使用 -e 選項:
-e, --rsh=COMMAND 指定遠端使用的shell命令

Use rsync -e ssh to specify which remote shell to use. In this case, rsync will use ssh.

在一下特殊的使用場景中, 我們不希望拷貝文件時, 我們不希望拷貝過程覆蓋掉目標位置中用戶做出的修改. 這時我們需要使用 -u 選項明確的告訴rsync命令保留用戶在目標文件中作出的修改. 在下面的例子中, 文件Basenames是用戶基於上次的拷貝, 修改過的文件, 當我們使用了-u 選項後, 該文件中的修改將不會被覆蓋掉.

在某些特殊場景中, 我們只需要遠程伺服器上的目錄結構, 而不希望花大量時間, 帶寬拷貝文件內容, 這時我們可以使用 -d, --dirs選項來達到目的.

有時我們希望拷貝文件時, 能實時的顯示拷貝進度, 以及傳輸速率等信息. 尤其是拷貝大文件時, 程序不輸出信息, 用戶往往無法區分程序是在響應中, 還是已經掛起, 在這種情況下如果使用 –progress 就會非常有幫助.
rsync –progress option displays detailed progress of rsync execution as shown below.

你也可以使用rsnapshot工具 (rsnapshot會調用rsync)來備份本地linux伺服器, 或者備份遠程linux伺服器.

有時我們希望目標文件和源文件保持嚴格一致, 不要多文件也不要少文件, 這是我們可能需要使用 -delete 選項來達到目的. 如果使用 -delete 選項, rsync將刪除目標位置多餘的文件或文件夾. 此選項還可以結合--delete-excluded 選項一起使用, 添加一些例外的文件.

上述示例中, new-file.txt 是源文件中沒有的文件, 其將會在拷貝時被刪除掉.

在某些特殊的場景下, 我們只想更新, 目標位置已經存在的文件或目錄, 而不關心源位置的新文件, 這時我們可以使用-existing 選項僅僅更新已經存在的文件.
讓我們來驗證一下這個選項的功能, 首先在源端添加一個新文件 new-file.txt.

從上面的例子可以看到, 由於加了--existing選項新文件new-file.txt沒有被拷貝到目標位置

選項-i, --itemize-changes 非常有用, 當我們想了解目標位置和源位置的文件差異時.

在源端:

在目標端:

注意: 在上面的例子中, 源位置和目標位置有兩處差異. 第一, 源文件Basenames的所有者和組 與 目標文件不同, 第一Dirnames文件大小也不一樣.
現在讓我們來看看rsync會怎樣顯示這些差異

輸出信息只在相應文件前面顯示了9個字母來標識改變, 這些字母具體是什麼意思呢? 請參考以下詳細說明

rsync 可以使用--include 和 --exclude 選項結合通配符進行文件或文件夾過濾

在上面的示例中, 僅僅以P打頭的文件和文件夾被包含了進來, 其他的文件都被過濾在拷貝的過程中被排除在外了.

可以使用--max-size 告訴rsync 不要拷貝大小超過某個值的文件, 可以使用K, M, G指定文件大小, M for megabytes and G for gigabytes.

rsync 有個重要優點就是, 可以做到在拷貝的過程中, 只拷貝發生變化了的部分, 而不是發送整個文件.
但是在某些場景中, 比如文件較少, 文件size較小時, 我們的帶寬又足夠大, cpu資源相對又貧乏, 我們不希望它這樣做, 因為畢竟計算源端和目標端的checksum, 並做對比, 也需要額外cpu開銷. 這時我們可以使用 -W, --whole-file 選項, 讓rsync不用計算那麼多, 一上來就直接開始傳送文件. 我們可以像下面這么做.

15個Rsync命令實例

『叄』 如何在java程序中調用linux命令或者shell腳本

//實現遠程連接Connectionconn=newConnection(scpAddr,Integer.parseInt(scpPort));conn.connect();//連接logger.debug("登陸遠程伺服器:"+scpUserName+","+scpPassword);//登陸遠程伺服器的用戶名密碼booleanisAuthed=conn.authenticateWithPassword(scpUserName,scpPassword);//登陸失敗if(!isAuthed){logger.debug("登陸遠程伺服器失敗");returnfalse;}SessionsshSession=conn.openSession();logger.debug("cd/&&rm-f"+file+"&&pwd");//linux命令sshSession.execCommand("cd/&&rm-f"+file+"&&pwd");//執行sshSession.close();conn.close();

『肆』 如何使用Windows下cwRsync搭建步驟文件詳細同步教程

詳細配置步驟如下:

一、伺服器端安裝配置

1、下載服務端安裝文件/softs/55933.html

服務端是安裝在「需要被同步的數據所在的伺服器」

2、安裝服務端

默認一直下一步;到下圖所示

這一步很重要,可以說是cwRsync安裝成功與否的關鍵。這一步會在當前系統下生成SvcCWRSYNC一個賬戶,用來啟動RsyncServer服務。建議這個對此賬戶的密碼進行重新設置,從新設置密碼後,需要在服務中更改,否則RsyncServer服務不能啟動

程序自動設置程序目錄可修改的許可權,因為需要寫日誌文件。

配置文件默認在程序的安裝目錄下,默認是 C:Program FilesICW

3、修改配置文件rsyncd.conf

use chroot = false

strict modes = false

hosts allow = *

log file = rsyncd.log

# Mole definitions

# Remember cygwin naming conventions : c:work becomes /cygwin/c/work

#

[test]

path = /cygdrive/c/work

read only = false

transfer logging = yes

修改配置內容如下,參數解釋:

use chroot = false # 不使用chroot

strict modes = false #使用靜態模式

pid file = rsyncd.pid # 日誌記錄文件

log file = rsyncd.log # 日誌記錄文件

[test] # 這里是認證的模塊名,在client端需要指定

path = /cygdrive/e/bak # 需要做鏡像的目錄,如e/bak(此目錄需要給SvcCWRSYNC 賬戶的讀取許可權)

transfer logging = yes # 記錄傳輸日誌

read only = yes # 只讀

list = no # 不允許列文件

hosts allow = 192.168.0.0/255.255.252.0

hosts deny = * # 禁止除192.168.1.0/255.255.255.0段外的連接IP

uid = 0 #解決運行後的@ERROR: invalid uid 錯誤

gid = 0 #解決運行後的@ERROR: invalid gid錯誤

lock file = rsyncd.lock #解決文件被鎖定無法復制問題

#auth users = SvcCWRSYNC # 認證的用戶名,這里沒有這行,則表明是匿名 #secrets file = /cygdrive/c/pass/rsync.passwd # 認證文件名

創建認證文件 c/pass/rsync.passwd 內容格式:用戶:密碼,如SvcCWRSYNC:star888 啟動RsyncServer服務並保證開機自動重啟,伺服器端配置完畢。

二、客戶端安裝配置

1、下載客戶端安裝文件/softs/55934.html

2、安裝

一直下一步,安裝完成。

3、cwRsync客戶端不需要很復雜的.配置,需要設置環境變數path:c:Program FilescwRsyncbin

4、通過命令建一個批處理

@echo off #沒有密碼

set RSYNC_HOME=c:Program FilescwRsyncbin

cd %RSYNC_HOME%

d:

rsync -av rsync://192.168.2.242/test /cygdrive/e/test

@echo off #需要密碼

set RSYNC_HOME=c:Program FilescwRsyncbin

cd %RSYNC_HOME%

d:

rsync -avzP --progress -- --password-file=/cygdrive/c/pass/rsync.passwd [email protected]::test /cygdrive/e/test

意思是將192.168.2.242的服務端下的test模塊下的e:bak目錄同步到客戶端的e:test下

命令參數解釋:

-avzP

-a 參數,相當於-rlptgoD,-r 是遞歸 -l 是鏈接文件,意思是拷貝鏈接文件;-p 表示保持文件原有許可權;-t 保持文件原有時間;-g 保持文件原有用戶組;-o 保持文件原有屬主;-D 相當於塊設備文件;

-z 傳輸時壓縮;

-P 傳輸進度;

-v verbose,詳細模式輸出

-u是只同步已經更新的文件,避免沒有更新的文件被重復更新一次,不過要注意兩者機器時鍾的同步

--progress

顯示備份過程

--

刪除那些DST中SRC沒有的文件

--password-file

指定密碼文件,只需包含密碼而不用包含用戶名

[email protected]::test

SvcCWRSYNC 登陸伺服器端的用戶名

192.168.2.242 伺服器端的ip地址

test 伺服器端指定的認證模塊名,多個同步作業靠此模塊名區分

/cygdrive/e/test

存放伺服器端同步文件的本地目錄

4、配置系統作業,運行腳本選擇rsync.bat,客戶端配置完畢。

『伍』 java 調用 shell 腳本

在寫程序時,有時需要在java程序中調用shell腳本,可以通過Runtime的exec方法來調用shell程序,運行腳本。每個Java 應用程序都有一個Runtime 類實例,使應用程序能夠與其運行的環境相連接。通過Runtime對象可以返回運行環境的情況,包括CPU數,虛擬機內存大小等,並能夠通過exec方法調用執行命令。可以通過getRuntime 方法獲取當前Runtime實例。 public boolean ExeShell(){ Runtime rt = Runtime.getRuntime(); try { Process p = rt.exec(checkShellName); if(p.waitFor() != 0) return false; } catch (IOException e) { SysLog.error("沒有找到檢測腳本"); return false; } catch (InterruptedException e) { e.printStackTrace(); return false; } return true; } 其中p.waitFor()語句用來等待子進程結束,其返回值為進程結束退出碼。

『陸』 java 遠程調用,具體實現

1、使用java代碼通過ssh登陸linux並執行命令,正常情況下sshd服務都會有,知道用戶密碼就可以使用這種方式了。
2、要在遠程linux伺服器上執行命令,可以在linux伺服器上啟動一個服務做執行腳本的代理,不斷接受來自你這個項目發來的腳本信息,然後執行,再把結果返回給你項目中去。
第一種:以消息隊列的方式發送這些腳本信息,linux代理不斷接受,並返回結果。項目同時要不斷接受結果。
第二種:項目中產生的腳本,直接記錄到資料庫,linux上的代理訪問這個資料庫,獲取腳本信息,並將執行結果寫入資料庫。項目中輪詢執行結果。
上面我說的消息隊列可以採用activemq,或者rabbitmq這些。
命令執行,java中直接Runtime.getRuntime().exec(command);就行了。

『柒』 如何在java程序中調用linux命令或者shell腳本

做到這,主要依賴2個類:Process和Runtime。
首先看一下Process類:
ProcessBuilder.start() 和 Runtime.exec 方法創建一個本機進程,並返回 Process 子類的一個實例,
該實例可用來控制進程並獲得相關信息。Process 類提供了執行從進程輸入、執行輸出到進程、等待進程完成、
檢查進程的退出狀態以及銷毀(殺掉)進程的方法。
創建進程的方法可能無法針對某些本機平台上的特定進程很好地工作,比如,本機窗口進程,守護進程,Microsoft Windows
上的 Win16/DOS 進程,或者 shell 腳本。創建的子進程沒有自己的終端或控制台。它的所有標准 io(即 stdin、stdout 和 stderr)
操作都將通過三個流 (getOutputStream()、getInputStream() 和 getErrorStream()) 重定向到父進程。
父進程使用這些流來提供到子進程的輸入和獲得從子進程的輸出。因為有些本機平台僅針對標准輸入和輸出流提供有限的緩沖區大小,
如果讀寫子進程的輸出流或輸入流迅速出現失敗,則可能導致子進程阻塞,甚至產生死鎖。
當沒有 Process 對象的更多引用時,不是刪掉子進程,而是繼續非同步執行子進程。
對於帶有 Process 對象的 Java 進程,沒有必要非同步或並發執行由 Process 對象表示的進程。
特別需要注意的是:
1,創建的子進程沒有自己的終端控制台,所有標注操作都會通過三個流
(getOutputStream()、getInputStream() 和 getErrorStream()) 重定向到父進程(父進程可通過這些流判斷子進程的執行情況)
2,因為有些本機平台僅針對標准輸入和輸出流提供有限的緩沖區大小,如果讀寫子進程的輸出流或輸入流迅速出現失敗,
則可能導致子進程阻塞,甚至產生死鎖
abstract void destroy()
殺掉子進程。
abstract int exitValue()
返回子進程的出口值。根據慣例,值0表示正常終止。
abstract InputStream getErrorStream()
獲取子進程的錯誤流。
abstract InputStream getInputStream()
獲取子進程的輸入流。
abstract OutputStream getOutputStream()
獲取子進程的輸出流。
abstract int waitFor()
導致當前線程等待,如有必要,一直要等到由該 Process 對象表示的進程已經終止。
如果已終止該子進程,此方法立即返回。如果沒有終止該子進程,調用的線程將被阻塞,直到退出子進程。
特別需要注意:如果子進程中的輸入流,輸出流或錯誤流中的內容比較多,最好使用緩存(注意上面的情況2)
再來看一下Runtime類:
每個Java應用程序都有一個Runtime類實例,使應用程序能夠與其運行的環境相連接。可以通過getRuntime方法獲取當前運行時環境。
應用程序不能創建自己的Runtime類實例。
介紹幾個主要方法:
Process exec(String command)
在單獨的進程中執行指定的字元串命令。
Process exec(String command, String[] envp)
在指定環境的單獨進程中執行指定的字元串命令。
Process exec(String command, String[] envp, File dir)
在有指定環境和工作目錄的獨立進程中執行指定的字元串命令。
Process exec(String[] cmdarray)
在單獨的進程中執行指定命令和變數。
Process exec(String[] cmdarray, String[] envp)
在指定環境的獨立進程中執行指定命令和變數。
Process exec(String[] cmdarray, String[] envp, File dir)
在指定環境和工作目錄的獨立進程中執行指定的命令和變數。
command:一條指定的系統命令。
envp:環境變數字元串數組,其中每個環境變數的設置格式為name=value;如果子進程應該繼承當前進程的環境,則該參數為null。
dir:子進程的工作目錄;如果子進程應該繼承當前進程的工作目錄,則該參數為null。
cmdarray:包含所調用命令及其參數的數組。
以下為示例(要打成可執行jar包扔到linux下執行):
public class test {
public static void main(String[] args){
InputStream in = null;
try {
Process pro = Runtime.getRuntime().exec(new String[]{"sh",
"/home/test/test.sh","select admin from M_ADMIN",
"/home/test/result.txt"});
pro.waitFor();
in = pro.getInputStream();
BufferedReader read = new BufferedReader(new InputStreamReader(in));
String result = read.readLine();
System.out.println("INFO:"+result);
} catch (Exception e) {
e.printStackTrace();
}
}
}
在這用的是Process exec(String[] cmdarray)這個方法
/home/test/test.sh腳本如下:
#!/bin/sh

#查詢sql
SQL=$1
#查詢結果保存文件
RESULT_FILE=$2
#資料庫連接
DB_NAME=scott
DB_PWD=tiger
DB_SERVER=DB_TEST

RESULT=`sqlplus -S ${DB_NAME}/${DB_PWD}@${DB_SERVER}<< !
set heading off
set echo off
set pages 0
set feed off
set linesize 3000
${SQL}
/
commit
/
!`

echo "${RESULT}" >> ${RESULT_FILE}
echo 0;
特別需要注意的是,當需要執行的linux命令帶有管道符時(例如:ps -ef|grep java),用上面的方法是不行的,解決方式是將需要執行的命令作為參數傳給shell
public class Test {
public static void main(String[] args) throws Exception{
String[] cmds = {"/bin/sh","-c","ps -ef|grep java"};
Process pro = Runtime.getRuntime().exec(cmds);
pro.waitFor();
InputStream in = pro.getInputStream();
BufferedReader read = new BufferedReader(new InputStreamReader(in));
String line = null;
while((line = read.readLine())!=null){
System.out.println(line);
}
}
}

PS:
Runtime.getRuntime().exec()這種調用方式在java虛擬機中是十分消耗資源的,即使命令可以很快的執行完畢,頻繁的調用時創建進程消耗十分客觀。
java虛擬機執行這個命令的過程是,首先克隆一條和當前虛擬機擁有一樣環境變數的進程,再用這個新的進程執行外部命令,最後退出這個進程。頻繁的創建對CPU和內存的消耗很大。

『捌』 2020-02-29 Rsync企業級全網備份項目案例實踐

某公司里有一台Web伺服器,裡面的數據很重要,但是如果硬碟壞了數據就會丟失,現在領導要求把數據做備份,這樣Web伺服器數據丟失在可以進行恢復,要求如下:
每天晚上00點整在Web伺服器A上打包備份系統配置文件、網站程序目錄及訪問日誌並通過rsync命令推送到伺服器B上備份保留(備份思路可以是先在本地按日期打包,然後再推到備份伺服器B上)。
已知3台伺服器主機名分別為Web01、BACKUP、NFS01,主機信息建下表。

(1)備份要求
每天晚上00點整在Web伺服器上打包備份系統配置文件、網站程序目錄及訪問日誌並通過rsync命令推送到備份伺服器BACKUP上備份保留。
(2)備份思路
可以是先在本地按日期打包,然後再推送到備份伺服器BACKUP上;NFS存儲伺服器和Web伺服器在實際工作中就是運維主要管理的全部伺服器。

1)所有伺服器的備份目錄必須都為/backup。
2)要備份的系統配置文件包括但不限於:

3)Web伺服器站點目錄假定為/var/html/www,如果沒有,可以先模擬創建。
4)Web伺服器訪問日誌路徑假定為/app/logs,如果沒有,可以先模擬創建。
5)Web伺服器本地保留打包後的7天備份數據即可(本地留存不能多於7天,因為數據太多硬碟會滿)。
6)備份伺服器BACKUP上,保留最近7天所有備份數據,保留6個月內每周一的所有數據副本。
7)備份伺服器上,要按照備份數據伺服器內網IP為目錄保存備份,備份的文件按照時間、名稱保存。
8)需要確保備份的數據盡量完整准確,在備份伺服器上對備份的數據是否完整進行檢查。
9)備份伺服器BACKUP上,每天早晨8:00把備份成功或失敗結果信息發送到系統管理員郵箱里。

初始化3台伺服器並將其作為全網備份方案測試伺服器,3台伺服器基本規劃信息如下:

(1)搭建備份伺服器

(2)Web伺服器搭建部署

(3)NFS伺服器搭建部署

第一個里程碑:在BACKUP上部署Rsync服務
在BACKUP Server上部署Rsync服務(前面有講,這里忽略),並且在Web01和NFS01客戶端伺服器測試推送成功。
第二個里程碑:客戶端本地開發打腳本
Nginx webserver,NFS dataserver本地打包備份腳本實現。
1)Web01伺服器待備份信息。

Web站點目錄與日誌目錄創建完畢後,開始編寫腳本信息(腳本編寫信息需要在命令行測試成功後再放入腳本文件中)。

第三個里程碑:配置定時任務
1)編輯定時任務,實現每天00:00定時備份本地數據,並推送到備份數據Rsync伺服器上。

2)編輯服務端刪除文件腳本文件,刪除180天前的所有備份數據,但保存每周一的。

3)配置定時任務,實現服務端180天前數據自動刪除。

第四個里程碑:數據傳輸完整性驗證與監控告警
服務端針對客戶端備份時的md5指紋數據,利用MD5命令進行驗證,完成數據傳輸過程完整性驗證。

第五個里程碑:配置mail使用外部SMTP發郵件
安裝mailx

編輯/etc/mail.rc配置文件

各命令參數的含義說明如下:

配置成功後,測試一下。

至此,全網備份方案完成。

『玖』 Linux下rsync怎麼用

rsync的命令格式可以為:

1. rsync [OPTION]... SRC [SRC]... [USER@]HOST:DEST
2. rsync [OPTION]... [USER@]HOST:SRC DEST
3. rsync [OPTION]... SRC [SRC]... DEST
4. rsync [OPTION]... [USER@]HOST::SRC [DEST]
5. rsync [OPTION]... SRC [SRC]... [USER@]HOST::DEST
6. rsync [OPTION]... rsync://[USER@]HOST[:PORT]/SRC [DEST]
rsync有六種不同的工作模式:
1. 拷貝本地文件;當SRC和DES路徑信息都不包含有單個冒號":"分隔符時就啟動這種工作模式。
2.使用一個遠程shell程序(如rsh、ssh)來實現將本地機器的內容拷貝到遠程機器。當DST路徑地址包含單個冒號":"分隔符時啟動該模式。
3.使用一個遠程shell程序(如rsh、ssh)來實現將遠程機器的內容拷貝到本地機器。當SRC地址路徑包含單個冒號":"分隔符時啟動該模式。
4. 從遠程rsync伺服器中拷貝文件到本地機。當SRC路徑信息包含"::"分隔符時啟動該模式。
5. 從本地機器拷貝文件到遠程rsync伺服器中。當DST路徑信息包含"::"分隔符時啟動該模式。
6. 列遠程機的文件列表。這類似於rsync傳輸,不過只要在命令中省略掉本地機信息即可。
-a 以archive模式操作、復制目錄、符號連接 相當於-rlptgoD
rsync中的參數
-r 是遞歸
-l 是鏈接文件,意思是拷貝鏈接文件;-p 表示保持文件原有許可權;-t 保持文件原有時間;-g 保持文件原有用戶組;-o 保持文件原有屬主;-D 相當於塊設備文件;
-z 傳輸時壓縮;
-P 傳輸進度;
-v 傳輸時的進度等信息,和-P有點關系,自己試試。可以看文檔;
-e ssh的參數建立起加密的連接。
-u只進行更新,防止本地新文件被重寫,注意兩者機器的時鍾的同時
--progress是指顯示出詳細的進度情況
--delete是指如果伺服器端刪除了這一文件,那麼客戶端也相應把文件刪除,保持真正的一致
--password-file=/password/path/file來指定密碼文件,這樣就可以在腳本中使用而無需互動式地輸入驗證密碼了,這里需要注意的是這份密碼文件許可權屬性要設得只有屬主可讀。
B、一些實例
B1、列出rsync 伺服器上的所提供的同步內容;
首先:我們看看rsync伺服器上提供了哪些可用的數據源
# rsync --list-only [email protected]::
++++++++++++++++++++++++++++++++++++++++++++++
Welcome to use the mike.org.cn rsync services!
2002------2009
++++++++++++++++++++++++++++++++++++++++++++++
rhel4home This is RHEL 4 data
註:前面是rsync所提供的數據源,也就是我們在rsyncd.conf中所寫的[rhel4home]模塊。而「This is RHEL 4 data」是由[rhel4home]模塊中的 comment = This is RHEL 4 data 提供的;為什麼沒有把rhel4opt數據源列出來呢?因為我們在[rhel4opt]中已經把list=no了。
$ rsync --list-only [email protected]::::rhel4home
++++++++++++++++++++++++++++++++++++++++++++++
Welcome to use the mike.org.cn rsync services!
2002------2009
++++++++++++++++++++++++++++++++++++++++++++++
Password:
drwxr-xr-x 4096 2009/03/15 21:33:13 .
-rw-r--r-- 1018 2009/03/02 02:33:41 ks.cfg
-rwxr-xr-x 21288 2009/03/15 21:33:13 wgetpaste
drwxrwxr-x 4096 2008/10/28 21:04:05 cvsroot
drwx------ 4096 2008/11/30 16:30:58 easylife
drwsr-sr-x 4096 2008/09/20 22:18:05 giddir
drwx------ 4096 2008/09/29 14:18:46 quser1
drwx------ 4096 2008/09/27 14:38:12 quser2
drwx------ 4096 2008/11/14 06:10:19 test
drwx------ 4096 2008/09/22 16:50:37 vbird1
drwx------ 4096 2008/09/19 15:28:45 vbird2
後面的root@ip中,root是指定密碼文件中的用戶名,之後的::rhel4home這是rhel4home模塊名
B2、rsync客戶端同步數據;
#rsync -avzP [email protected]::rhel4home rhel4home
Password: 這里要輸入root的密碼,是伺服器端rsyncd.secrets提供的。在前面的例子中我們用的是mike,輸入的密碼並不回顯,輸好就回車。
註: 這個命令的意思就是說,用root用戶登錄到伺服器上,把rhel4home數據,同步到本地當前目錄rhel4home上。當然本地的目錄是可以你自己 定義的。如果當你在客戶端上當前操作的目錄下沒有rhel4home這個目錄時,系統會自動為你創建一個;當存在rhel4home這個目錄中,你要注意 它的寫許可權。
#rsync -avzP --delete [email protected]::rhel4home rhel4home
這回我們引入一個--delete 選項,表示客戶端上的數據要與伺服器端完全一致,如果 linuxsirhome目錄中有伺服器上不存在的文件,則刪除。最終目的是讓linuxsirhome目錄上的數據完全與伺服器上保持一致;用的時候要 小心點,最好不要把已經有重要數所據的目錄,當做本地更新目錄,否則會把你的數據全部刪除;
設定 rsync client
設定密碼文件
#rsync -avzP --delete --password-file=rsyncd.secrets [email protected]::rhel4home rhel4home
這次我們加了一個選項 --password-file=rsyncd.secrets,這是當我們以root用戶登錄rsync伺服器同步數據時,密碼將讀取rsyncd.secrets這個文件。這個文件內容只是root用戶的密碼。我們要如下做;
# touch rsyncd.secrets
# chmod 600 rsyncd.secrets
# echo "mike"> rsyncd.secrets
# rsync -avzP --delete --password-file=rsyncd.secrets [email protected]::rhel4home rhel4home
註:這里需要注意的是這份密碼文件許可權屬性要設得只有屬主可讀。
這樣就不需要密碼了;其實這是比較重要的,因為伺服器通過crond 計劃任務還是有必要的;
B3、讓rsync客戶端自動與伺服器同步數據
伺服器是重量級應用,所以數據的網路備份還是極為重要的。我們可以在生產型伺服器上配置好rsync 伺服器。我們可以把一台裝有rysnc機器當做是備份伺服器。讓這台備份伺服器,每天在早上4點開始同步伺服器上的數據;並且每個備份都是完整備份。有時 硬碟壞掉,或者伺服器數據被刪除,完整備份還是相當重要的。這種備份相當於每天為伺服器的數據做一個鏡像,當生產型伺服器發生事故時,我們可以輕松恢復數 據,能把數據損失降到最低;是不是這么回事??
step1:創建同步腳本和密碼文件

#mkdir /etc/cron.daily.rsync
#cd /etc/cron.daily.rsync
#touch rhel4home.sh rhel4opt.sh
#chmod 755 /etc/cron.daily.rsync/*.sh
#mkdir /etc/rsyncd/
#touch /etc/rsyncd/rsyncrhel4root.secrets
#touch /etc/rsyncd/rsyncrhel4easylife.secrets
#chmod 600 /etc/rsyncd/rsync.*
註: 我們在 /etc/cron.daily/中創建了兩個文件rhel4home.sh和rhel4opt.sh ,並且是許可權是755的。創建了兩個密碼文件root用戶用的是rsyncrhel4root.secrets ,easylife用戶用的是 rsyncrhel4easylife.secrets,許可權是600;
我們編輯rhel4home.sh,內容是如下的:
#!/bin/sh
#backup 192.168.145.5:/home
/usr/bin/rsync -avzP --password-file=/etc/rsyncd/rsyncrhel4root.password [email protected]::rhel4home /home/rhel4homebak/$(date +'%m-%d-%y')
我們編輯 rhel4opt.sh ,內容是:
#!/bin/sh
#backup 192.168.145.5:/opt
/usr/bin/rsync -avzP --password-file=/etc/rsyncd/rsyncrhel4easylife.secrets [email protected]::rhel4opt /home/rhel4hoptbak/$(date +'%m-%d-%y')
註:你可以把rhel4home.sh和rhel4opt.sh的內容合並到一個文件中,比如都寫到rhel4bak.sh中;
接著我們修改 /etc/rsyncd/rsyncrhel4root.secrets和rsyncrhel4easylife.secrets的內容;
# echo "mike" > /etc/rsyncd/rsyncrhel4root.secrets
# echo "keer"> /etc/rsyncd/rsyncrhel4easylife.secrets
然後我們再/home目錄下創建rhel4homebak 和rhel4optbak兩個目錄,意思是伺服器端的rhel4home數據同步到備份伺服器上的/home/rhel4homebak 下,rhel4opt數據同步到 /home/rhel4optbak/目錄下。並按年月日歸檔創建目錄;每天備份都存檔;
#mkdir /home/rhel4homebak
#mkdir /home/rhel4optbak
step2:修改crond伺服器的配置文件 加入到計劃任務
#crontab -e
加入下面的內容:
# Run daily cron jobs at 4:10 every day backup rhel4 data:
10 4 * * * /usr/bin/run-parts /etc/cron.daily.rsync 1> /dev/null
註:第一行是注釋,是說明內容,這樣能自己記住。
第二行表示在每天早上4點10分的時候,運行 /etc/cron.daily.rsync 下的可執行腳本任務;

配置好後,要重啟crond 伺服器;
# killall crond 註:殺死crond 伺服器的進程;
# ps aux |grep crond 註:查看一下是否被殺死;
# /usr/sbin/crond 註:啟動 crond 伺服器;
# ps aux |grep crond 註:查看一下是否啟動了?
root 3815 0.0 0.0 1860 664 ? S 14:44 0:00 /usr/sbin/crond
root 3819 0.0 0.0 2188 808 pts/1 S+ 14:45 0:00 grep crond

『拾』 怎麼通過java去調用並執行shell腳本以及問題總結

對於第一個問題:java抓取,並且把結果打包。那麼比較直接的做法就是,java接收各種消息(db,metaq等等),然後藉助於jstorm集群進行調度和抓取。
最後把抓取的結果保存到一個文件中,並且通過調用shell打包, 回傳。 也許有同學會問,
為什麼不直接把java調用odps直接保存文件,答案是,我們的集群不是hz集群,直接上傳odps速度很有問題,因此先打包比較合適。(這里不糾結設計了,我們回到正題)

java調用shell的方法

通過ProcessBuilder進行調度

這種方法比較直觀,而且參數的設置也比較方便, 比如我在實踐中的代碼(我隱藏了部分業務代碼):

ProcessBuilderpb = new ProcessBuilder("./" + RUNNING_SHELL_FILE, param1,
param2, param3);
pb.directory(new File(SHELL_FILE_DIR));
int runningStatus = 0;
String s = null;
try {
Process p = pb.start();
try {
runningStatus = p.waitFor();
} catch (InterruptedException e) {
}

} catch (IOException e) {
}
if (runningStatus != 0) {
}
return;

這里有必要解釋一下幾個參數:

RUNNING_SHELL_FILE:要運行的腳本

SHELL_FILE_DIR:要運行的腳本所在的目錄; 當然你也可以把要運行的腳本寫成全路徑。

runningStatus:運行狀態,0標識正常。 詳細可以看java文檔。

param1, param2, param3:可以在RUNNING_SHELL_FILE腳本中直接通過1,2,$3分別拿到的參數。

直接通過系統Runtime執行shell

這個方法比較暴力,也比較常用, 代碼如下:

p = Runtime.getRuntime().exec(SHELL_FILE_DIR + RUNNING_SHELL_FILE + " "+param1+" "+param2+" "+param3);
p.waitFor();

我們發現,通過Runtime的方式並沒有builder那麼方便,特別是參數方面,必須自己加空格分開,因為exec會把整個字元串作為shell運行。

可能存在的問題以及解決方法

如果你覺得通過上面就能滿足你的需求,那麼可能是要碰壁了。你會遇到以下情況。

沒許可權運行

這個情況我們團隊的朱東方就遇到了, 在做DTS遷移的過程中,要執行包裡面的shell腳本, 解壓出來了之後,發現執行不了。 那麼就按照上面的方法授權吧

java進行一直等待shell返回

這個問題估計更加經常遇到。 原因是, shell腳本中有echo或者print輸出, 導致緩沖區被用完了! 為了避免這種情況, 一定要把緩沖區讀一下, 好處就是,可以對shell的具體運行狀態進行log出來。 比如上面我的例子中我會變成:

ProcessBuilderpb = new ProcessBuilder("./" + RUNNING_SHELL_FILE, keyword.trim(),
taskId.toString(), fileName);
pb.directory(new File(CASPERJS_FILE_DIR));
int runningStatus = 0;
String s = null;
try {
Process p = pb.start();
BufferedReaderstdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
BufferedReaderstdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
while ((s = stdInput.readLine()) != null) {
LOG.error(s);
}
while ((s = stdError.readLine()) != null) {
LOG.error(s);
}
try {
runningStatus = p.waitFor();
} catch (InterruptedException e) {
}

記得在start()之後, waitFor()之前把緩沖區讀出來打log, 就可以看到你的shell為什麼會沒有按照預期運行。 這個還有一個好處是,可以讀shell裡面輸出的結果, 方便java代碼進一步操作。

也許你還會遇到這個問題,明明手工可以運行的命令,java調用的shell中某一些命令居然不能執行,報錯:命令不存在!

比如我在使用casperjs的時候,手工去執行shell明明是可以執行的,但是java調用的時候,發現總是出錯。
通過讀取緩沖區就能發現錯誤日誌了。 我發現即便自己把安裝的casperjs的bin已經加入了path中(/etc/profile,
各種bashrc中)還不夠。 比如:

exportNODE_HOME="/home/admin/node"
exportCASPERJS_HOME="/home/admin/casperjs"
exportPHANTOMJS_HOME="/home/admin/phantomjs"
exportPATH=$PATH:$JAVA_HOME/bin:/root/bin:$NODE_HOME/bin:$CASPERJS_HOME/bin:$PHANTOMJS_HOME/bin

原來是因為java在調用shell的時候,默認用的是系統的/bin/下的指令。特別是你用root許可權運行的時候。 這時候,你要在/bin下加軟鏈了。針對我上面的例子,就要在/bin下加軟鏈:

ln -s /home/admin/casperjs/bin/casperjscasperjs;
ln -s /home/admin/node/bin/nodenode;
ln -s /home/admin/phantomjs/bin/phantomjsphantomjs;

這樣,問題就可以解決了。

如果是通過java調用shell進行打包,那麼要注意路徑的問題了

因為shell裡面tar的壓縮和解壓可不能直接寫:

tar -zcf /home/admin/data/result.tar.gz /home/admin/data/result

直接給你報錯,因為tar的壓縮源必須到路徑下面, 因此可以寫成

tar -zcf /home/admin/data/result.tar.gz -C /home/admin/data/ result

如果我的shell是在jar包中怎麼辦?

答案是:解壓出來。再按照上面指示進行操作。(1)找到路徑

String jarPath = findClassJarPath(ClassLoaderUtil.class);
JarFiletopLevelJarFile = null;
try {
topLevelJarFile = new JarFile(jarPath);
Enumeration<JarEntry> entries = topLevelJarFile.entries();
while (entries.hasMoreElements()) {
JarEntryentry = entries.nextElement();
if (!entry.isDirectory() && entry.getName().endsWith(".sh")) {
對你的shell文件進行處理
}
}

對文件處理的方法就簡單了,直接touch一個臨時文件,然後把數據流寫入,代碼:

FileUtils.touch(tempjline);
tempjline.deleteOnExit();
FileOutputStreamfos = new FileOutputStream(tempjline);
IOUtils.(ClassLoaderUtil.class.getResourceAsStream(r), fos);
fos.close();