需求:
以前,手動上傳配置文件到服務器,然後手工複製到另外一臺服務器上,然後登陸SSH Secure File Transfer Client客戶端,執行相關shell命令號
現在這些操作需要一鍵完成,即文件複製到另一臺服務器,登陸ssh客戶端,切換用戶,執行導入命令行
解決辦法:
- 獲得應用程序所在的機器用戶名和密碼,然後執行shell腳本完成以上操作
未採用:因爲運維不提供應用服務器的用戶名和密碼 - 直接連接另一臺服務器,執行復制文件,然後執行shell腳本(採取)
要上傳文件到linux服務器上,使用FTP協議,公司linux服務器上需要ftp客戶端需要安全驗證,比較麻煩,所以想到使用sftp來解決,sftp是基於ssh的安全協議的ftp協議,Java中有JSch包來實現連接服務器。
第一步:下載JSch包,請從官網下載它:http://www.jcraft.com/jsch/
第二步:新建FtpsFileList.java文件
//只有上傳方法,也可以有下載文件方法
public class FtpsFileList {
private static final Logger LOG = LoggerFactory.getLogger(FtpsFileList.class);
//將本地的dirFile這個文件複製到遠程服務器上的desFile文件夾下
public static void loadFile(String host, int port, String username, final String password, String dirFile,String desFile) {
ChannelSftp sftp = null;
Channel channel = null;
Session sshSession = null;
try {
JSch jsch = new JSch();//創建一個jsch對象
jsch.getSession(username, host, port);
// 根據用戶名,主機ip,端口獲取一個Session對象
sshSession = jsch.getSession(username, host, port);
//設置密碼
sshSession.setPassword(password);
Properties sshConfig = new Properties();
sshConfig.put("StrictHostKeyChecking", "no");
// 爲Session對象設置properties
sshSession.setConfig(sshConfig);
sshSession.connect();
LOG.debug("Session connected!");
// 打開SFTP通道
channel = sshSession.openChannel("sftp");
// 建立SFTP通道的連接
channel.connect();
LOG.debug("Channel connected!");
sftp = (ChannelSftp) channel;
//InputStream is = sftp.get("/ftp/re/20140713.dat");
InputStream fis = new FileInputStream(new File(dirFile));
//文件上傳(通過inputstream流來實現) 詳見https://www.cnblogs.com/longyg/archive/2012/06/25/2556576.html
sftp.put(fis,desFile);
LOG.info("文件複製到服務器成功!\r");
} catch (Exception e) {
e.printStackTrace();
} finally {
closeChannel(sftp);
closeChannel(channel);
closeSession(sshSession);
}
}
private static void closeChannel(Channel channel) {
if (channel != null) {
if (channel.isConnected()) {
channel.disconnect();
}
}
}
private static void closeSession(Session session) {
if (session != null) {
if (session.isConnected()) {
session.disconnect();
}
}
}
}
調用方式:
FtpsFileList.loadFile("10.31.92.70", 22, "serviceop", "115LbUrAbEsZw","/nfsc/qhcs-ansir-stg1/ansir/HanLP/xiaodai/loan-freebase.ttl","/wls/serviceop/virtuoso_script/loanXD.ttl");
logger.info("ttl文件複製成功");
到這一步,已經完成上傳文件到linux服務器上
第三步:寫好shell腳本(關鍵核心),這一步學習了好多東西,發現shell命令挺好玩的
#!/usr/bin/expect
spawn ssh serviceop@10.31.92.70
set timeout 2
expect "password:"
send "115LbUrAbEsZw\r"
expect "*]#"
set password "wuxin952"
spawn su root
expect "password:"
send "wuxin952\r"
expect "#"
send "/wls/serviceop/virtuoso-opensource/home/bin/isql localhost:13002\r"
send "DB.DBA.TTLP_MT(file_to_string_output('/wls/serviceop/virtuoso_script/loan.ttl'),'','http://www.xiaowei.com');\r"
interact
註釋:因爲需要交互式輸入密碼,所以選擇使用expect命令環境來執行
具體釋義見:
第四步:java代碼調用shell腳本,代碼如下,
Process類是一個抽象類,用於定義一個本地進程,Runtime.getRuntime().exec(sh)返回一個進程對象
具體見:process
//授予權利給shell腳本呢
Process ps1=Runtime.getRuntime().exec("chmod 777 /nfsc/qhcs-ansir-stg1/ansir/HanLP/xiaodai/bash_scp.sh");
//等待當前線程執行完,等待返回process類對象表示的進程結束
ps1.waitFor();
logger.info("chmod命令執行結束");
BufferedReader br1 = new BufferedReader(new InputStreamReader(ps1.getInputStream()));
while ((line = br1.readLine()) != null) {
logger.info("chmod命令結果:"+line);
}
//實際調用使用expect 文件
Process ps2=Runtime.getRuntime().exec("expect /nfsc/qhcs-ansir-stg1/ansir/HanLP/xiaodai/bash_scp.sh");
ps2.waitFor();
logger.info("expect命令執行結束");
BufferedReader br2 = new BufferedReader(new InputStreamReader(ps2.getInputStream()));
while ((line = br2.readLine()) != null) {
logger.info("expect命令結果:"+line);
}
String result = sb.toString();
logger.info("expect整理結果爲:"+result);
後續shell命令見下一篇博客