


Bagaimanakah Java antara muka dengan platform operasi dan penyelenggaraan automatik Ansible?
Java menyambung kepada platform operasi dan penyelenggaraan automatik yang boleh digunakan untuk merealisasikan pengumpulan dan pengedaran fail
Sambungan ini terutamanya mempunyai dua fungsi berikut:
Pengumpulan Fail (operasi kelompok pada fail, termasuk pengumpulan kumpulan fail biasa seperti fail log daripada berbilang hos)
Pengedaran fail (operasi kelompok pada fail, termasuk pengumpulan kumpulan fail daripada berbilang hos) Edarkan fail biasa seperti fail log)
Penerangan senario dan pemasangan ansible yum
Oleh kerana ansible tidak mempunyai pakej pemasangan Windows, persekitaran Linux telah dibina untuk memudahkan ujian.
Kali ini, kaedah yum digunakan untuk memasang Ansible Pertama, pasang sumber EPEL.
yum install -y http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
Lihat sumber EPEL Versi Ansible dalam
yum info ansible
terus pasang versi ini, jika ada keperluan lain, sila laraskan sumber dan pasang versi ansible lain
yum install -y ansible
Selepas pemasangan selesai, semak maklumat versi ansible
ansible --version
Konfigurasikan senarai pelayan Ansible
Fail inventori /etc/ansible/hosts, tulis alamat IP yang sepadan dan port hos nod dalam fail ini
I Saya hanya melakukan demonstrasi di sini Selepas IP, anda boleh menambah port SSH sebenar nod Terdapat senarai [] di atas kandungan yang ditakrifkan saya biasa memanggilnya sebagai senarai kumpulan
Pengesahan mudah dan ping hos yang ditambahkan
Ansible berjaya dipasang! !
Kod Java melaksanakan pengedaran fail
Seperti namanya, pengedaran fail adalah untuk mengedarkan fail setempat kepada berbilang hos.
Pada masa ini, anda memerlukan Apache POI (anda boleh mengimport pakej yang sepadan) untuk mencipta fail setempat (fail konfigurasi Hos yang boleh dibuat juga melalui POI)
Kelas alat fail penciptaan POI
package com.tiduyun.cmp.operation.utils; import com.tiduyun.cmp.common.model.operation.HostInfo; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.StringUtils; import org.springframework.stereotype.Component; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; /** * @author huyuan@tiduyun.com ansible创建文件 */ @Slf4j @Component public class AnsibleCreateFileUtils { private final static String filename = "hosts"; public static String passWordConnect(List<HostInfo> hostInfo, String hostGroup , String directory) throws IOException{ /** 在本地新建一个文件夹 里面创建一个文件 向里面写入内容 */ // 创建文件夹对象 创建文件对象 File folder = new File(directory); // 如果文件夹不存在 就创建一个空的文件夹 if (!folder.exists()) { log.info("创建了文件夹{}" , folder); folder.mkdirs(); } File file = new File(directory, filename); // 如果文件不存在 就创建一个空的文件 if (!file.exists()) { try { log.info("创建了文件{}" , file); file.createNewFile(); } catch (IOException e) { log.error("error data{}" , e); } } // 写入数据 // 创建文件字节输出流 FileOutputStream fos = new FileOutputStream(file); try { List<String> list = new ArrayList<>(); for (HostInfo data : hostInfo) { // 开始写 String string = data.getHost() + " ansible_ssh_pass=" + data.getPasswd() + " ansible_ssh_user=" + data.getAccount() + " ansible_ssh_port=" + data.getPort(); list.add(string); } String splicingData = StringUtils.join(list, "\n"); String str = "[" + hostGroup + "]" + "\n" + splicingData; byte[] bytes = str.getBytes(); // 将byte数组中的所有数据全部写入 fos.write(bytes); fos.flush(); log.info("文件内容{}" , str); // 删除文件 // deleteFile(file); // 关闭流 } catch (IOException e) { log.error("error data{}" , e); throw e; }finally { if (fos != null) { fos.close(); } } return directory; } public static void deleteFile(File file) { if (file.exists()) {// 判断路径是否存在 if (file.isFile()) {// boolean isFile():测试此抽象路径名表示的文件是否是一个标准文件。 file.delete(); } else {// 不是文件,对于文件夹的操作 // 保存 路径D:/1/新建文件夹2 下的所有的文件和文件夹到listFiles数组中 File[] listFiles = file.listFiles();// listFiles方法:返回file路径下所有文件和文件夹的绝对路径 for (File file2 : listFiles) { /* * 递归作用:由外到内先一层一层删除里面的文件 再从最内层 反过来删除文件夹 * 注意:此时的文件夹在上一步的操作之后,里面的文件内容已全部删除 * 所以每一层的文件夹都是空的 ==》最后就可以直接删除了 */ deleteFile(file2); } } file.delete(); } else { log.error("该file路径不存在!!"); } } }
Buat fail konfigurasi kumpulan hos
Nota: Ansible dibahagikan kepada dua kaedah sambungan digunakan di sini, dan fail yang dijana mempunyai kunci yang disambungkan! ! ! Ini akan digunakan dalam pengumpulan dan pengedaran seterusnya. (Jika anda tidak faham, anda boleh mencari kaedah sambungan ansible)
@Override public void ansibleCreateHost(HostInfo hostInfo, String Key) { ParamCheckUtils.notNull(hostInfo, "hostInfo"); List<HostInfo> HostIp = Arrays.asList(hostInfo); for (HostInfo data : HostIp) { String ansiblePassWd = data.getPasswd(); String PassWd = hostInfoService.decode(ansiblePassWd); data.setPasswd(PassWd); } try { AnsibleCreateFileUtils.passWordConnect(HostIp, ansibleConfigurationItemVo.getHostGroup(), ansibleConfigurationItemVo.getDirectory()); } catch (IOException e) { log.error("Failed to create host configuration{}", e); } }
Laksanakan pengedaran fail
Fail konfigurasi hos telah dikonfigurasikan dan langkah seterusnya ialah untuk laksanakan arahan ansible yang sepadan, sambungkan perintah ansible melalui Java.
Kelas alat arahan pelaksanaan
<br/>
package com.tiduyun.cmp.operation.utils; import lombok.extern.slf4j.Slf4j; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.nio.charset.Charset; import static cn.hutool.db.DbUtil.close; /** * @author huyuan@tiduyun.com ansible执行命令工具类 * upload 上传文件 * createRemoteDirectory 创建远程目录 */ @Slf4j public class AnsibleExecuteTheOrderUtils { private final static String commandBin = "/bin/sh"; private final static String commandC = "-c"; /** * 创建远程目录 */ public static void createRemoteDirectory(String hostGroup, String remotePath, String directory) throws IOException { Runtime run = Runtime.getRuntime(); String[] cmds = new String[3]; cmds[0] = commandBin; cmds[1] = commandC; cmds[2] = "ansible " + hostGroup + " -m command -a " + "\"mkdir " + remotePath + "\"" + " -i " + directory + "/hosts"; // 执行CMD命令 Process p = run.exec(cmds); log.info("ansible远程执行命令为{}", cmds[2]); BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream(), Charset.forName("UTF-8"))); try { String lineMes; while ((lineMes = br.readLine()) != null) log.info(lineMes);// 打印输出信息 try { // 检查命令是否执行失败。 if (p.waitFor() != 0) { if (p.exitValue() == 1)// 0表示正常结束,1:非正常结束 log.error("命令执行失败"); } } catch (InterruptedException e) { log.error("error data{}", e); } } catch (IOException e) { log.error("fail to carry out command{}", e); throw e; } finally { if (br != null) { br.close(); } } } /** * 文件分发 */ public static void upload(String hostGroup, String localPath, String remotePath, String directory) throws IOException { Runtime run = Runtime.getRuntime(); String[] cmds = new String[3]; cmds[0] = commandBin; cmds[1] = commandC; cmds[2] = "ansible " + hostGroup + " -m copy -a " + "\"src=" + localPath + " dest=" + remotePath + "\"" + " -i " + directory + "/hosts"; // 执行CMD命令 Process p = run.exec(cmds); log.info("ansible命令为{}", cmds[2]); BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream(), Charset.forName("UTF-8"))); try { String lineMes; while ((lineMes = br.readLine()) != null) log.info("ansible输出信息为 :" + lineMes);// 打印输出信息 try { // 检查命令是否执行失败。 if (p.waitFor() != 0) { if (p.exitValue() == 1)// 0表示正常结束,1:非正常结束 log.error("命令执行失败"); } } catch (InterruptedException e) { log.error("error data{}", e); } } catch (IOException e) { log.error("fail to carry out command{}", e); throw e; } finally { if (br != null) { br.close(); } } } /** * 文件采集 */ public static void fileCollection(String hostGroup, String remotePath, String localPath , String directory) throws IOException { Runtime run = Runtime.getRuntime(); String[] cmds = new String[3]; cmds[0] = commandBin; cmds[1] = commandC; cmds[2] = "ansible " + hostGroup + " -m fetch -a " + "\"src=" + remotePath + " dest=" + localPath + " force=yes backup=yes\"" + " -i " + directory + "/hosts"; // 执行CMD命令 Process p = run.exec(cmds); log.info("ansible远程采集文件命令为{}", cmds[2]); BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream(), Charset.forName("UTF-8"))); try { String lineMes; while ((lineMes = br.readLine()) != null) log.info(lineMes);// 打印输出信息 try { // 检查命令是否执行失败。 if (p.waitFor() != 0) { if (p.exitValue() == 1)// 0表示正常结束,1:非正常结束 log.error("命令执行失败"); } } catch (InterruptedException e) { log.error("error data{}", e); } } catch (IOException e) { log.error("fail to carry out command{}", e); throw e; } finally { if (br != null) { br.close(); } } } public static void ExecuteTheOrder(String command) throws IOException { log.info("start execute cmd {}", command); String[] cmd = new String[] {"/bin/bash", "-c", command}; Runtime run = Runtime.getRuntime(); Process p = run.exec(cmd); // 执行CMD命令 BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream(), Charset.forName("UTF-8"))); try { String lineMes; while ((lineMes = br.readLine()) != null) log.info("输出信息为 {}", lineMes);// 打印输出信息 try { // 检查命令是否执行失败。 if (p.waitFor() != 0) { if (p.exitValue() == 1)// 0表示正常结束,1:非正常结束 log.error("命令执行失败"); } } catch (InterruptedException e) { log.error("error data{}", e); } } catch (IOException e) { log.error("fail to carry out command{}", e); throw e; } finally { if (br != null) { br.close(); } } } public static void disconnect() { try { close(); } catch (Exception ex) { // Ignore because disconnection is quietly } } // public void execute(String command) throws Exception { // log.info("start execute cmd {}", command); // try (Session session = sshClient.startSession()) { // Session.Command exec = session.exec(command); // // Integer readLineCount = 0; // InputStream in = exec.getInputStream(); // log.info(IOUtils.readFully(in).toString()); // String errorMessage = IOUtils.readFully(exec.getErrorStream(), LoggerFactory.DEFAULT).toString(); // log.info(errorMessage); // if (exec.getExitStatus() != null && exec.getExitStatus() != 0) { // throw new RuntimeException( // "exec " + command + " error,error message is " + errorMessage + ",error code " + exec.getExitStatus()); // } // log.info("exec result code {}", exec.getExitStatus()); // // } // // } }
Langkah seterusnya ialah memanggil
package com.tiduyun.cmp.operation.service.impl; import cn.hutool.core.util.RandomUtil; import cn.hutool.core.util.StrUtil; import com.tiduyun.cmp.common.model.flow.UploadFile; import com.tiduyun.cmp.common.model.operation.ComponentInfo; import com.tiduyun.cmp.common.model.operation.HostInfo; import com.tiduyun.cmp.common.provider.service.ExceptionBuildService; import com.tiduyun.cmp.operation.constant.OperationExceptionCode; import com.tiduyun.cmp.operation.constant.StartCmdSeparate; import com.tiduyun.cmp.operation.model.AnsibleConfigurationItemVo; import com.tiduyun.cmp.operation.model.vo.FileQueryVo; import com.tiduyun.cmp.operation.service.AnsibleTaskRecordService; import com.tiduyun.cmp.operation.service.ComposerDeployService; import com.tiduyun.cmp.operation.service.HostInfoService; import com.tiduyun.cmp.operation.service.UploadFileService; import com.tiduyun.cmp.operation.utils.AnsibleExecuteTheOrderUtils; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @Slf4j @Service public class AnsibleDeployServiceImpl implements ComposerDeployService { @Value(value = "${cmp.operation.commandHeader:cmd /c}") private String commandHeader; @Value(value = "${cmp.operation.filePath:/data/cmp/file}") private String filePath; @Value(value = "${cmp.operation.remoteFilePath:/tmp}") private String remoteFilePath; @Autowired private AnsibleTaskRecordService ansibleTaskRecordService; @Autowired private AnsibleConfigurationItemVo ansibleConfigurationItemVo; @Autowired private UploadFileService uploadFileService; @Autowired private HostInfoService hostInfoService; @Autowired private ExceptionBuildService exceptionBuildService; @Override public void deploy(HostInfo hostInfo, ComponentInfo componentInfo, String cpmposerName) { ansibleTaskRecordService.ansibleCreateHost(hostInfo, null); try { String remotePath = StringUtils.join(remoteFilePath, "/", cpmposerName, "-", componentInfo.getName(), "-", RandomUtil.randomString(3)); log.info("remote file path = {}", remotePath); List<Integer> fileIds = getFileIds(componentInfo.getFileUrl()); if (CollectionUtils.isNotEmpty(fileIds)) { FileQueryVo uploadFileQueryVo = new FileQueryVo(); uploadFileQueryVo.setIds(fileIds); List<UploadFile> uploadFiles = uploadFileService.query(uploadFileQueryVo); for (UploadFile uploadFile : uploadFiles) { String path = StringUtils.join(filePath, uploadFile.getFilePath()); File file = new File(path); if (!file.exists()) { log.error("file url is {}", file.getPath()); throw exceptionBuildService.buildException(OperationExceptionCode.FILE_NOT_EXIST, new Object[] {uploadFile.getFileName()}); } // 创建远程目录 AnsibleExecuteTheOrderUtils.createRemoteDirectory(ansibleConfigurationItemVo.getHostGroup(), StringUtils.join(remotePath), ansibleConfigurationItemVo.getDirectory()); // 分发文件 AnsibleExecuteTheOrderUtils.upload(ansibleConfigurationItemVo.getHostGroup(), path, StringUtils.join(remotePath, "/", uploadFile.getFileName()), ansibleConfigurationItemVo.getDirectory()); } } List<String> startCmds = getStartCmds(componentInfo.getStartCmd()); if (CollectionUtils.isNotEmpty(startCmds)) { String cdCmd = StringUtils.join("cd ", remotePath); String execCmd = StringUtils.join(startCmds, ";"); execCmd = StringUtils.join(cdCmd, ";", execCmd); log.info("execCmd= " + execCmd); // sshClient.execute(execCmd); AnsibleExecuteTheOrderUtils.ExecuteTheOrder(execCmd); } else { log.error("parse startCmd fail {}", componentInfo.getStartCmd()); } } catch (Exception e) { log.error("主机[{}]部署[{}]组件失败,主机ID[{}],组件ID[{}]:", hostInfo.getHost(), componentInfo.getName(), hostInfo.getId(), componentInfo.getId(), e); throw exceptionBuildService.buildException(OperationExceptionCode.EXECUTE_CMD_ERROR, new Object[] {e.getMessage()}); } finally { AnsibleExecuteTheOrderUtils.disconnect(); } } @Override public boolean isSupport(HostInfo hostInfo) { return true; } private List<Integer> getFileIds(String fileIds) { List<Integer> ids = new ArrayList<>(); if (fileIds == null) { return null; } String[] split = StringUtils.split(fileIds, ","); for (String s : split) { ids.add(Integer.parseInt(s)); } return ids; } private List<String> getStartCmds(String startCmd) { List<String> cmd = new ArrayList<>(); if (startCmd == null) { return cmd; } String[] split = StrUtil.split(startCmd, StartCmdSeparate.SIGN); cmd.addAll(Arrays.asList(split)); return cmd; } public static Boolean needCd(String s) { String[] splits = StrUtil.split(s, "&&"); int maxIndex = splits.length - 1; String cmd = splits[maxIndex]; if (StrUtil.startWith(cmd, "cd")) { return false; } else { return true; } } }
Fail koleksi
Sama seperti di atas, panggil dua kelas alat
@Override public void fileCollection(HostInfo hostInfo, String remotePath, String localPath) { ansibleCreateHost(hostInfo, null); try { log.info("remote file path = {}", remotePath); log.info("local file path = {}", localPath); // 文件采集 AnsibleExecuteTheOrderUtils.fileCollection(ansibleConfigurationItemVo.getHostGroup(), remotePath, localPath , ansibleConfigurationItemVo.getDirectory()); } catch (Exception e) { log.error("主机[{}]文件采集失败,主机ID[{}]:", hostInfo.getHost(), hostInfo.getId(), e); throw exceptionBuildService.buildException(OperationExceptionCode.EXECUTE_CMD_ERROR, new Object[] {e.getMessage()}); } finally { AnsibleExecuteTheOrderUtils.disconnect(); } }
Atas ialah kandungan terperinci Bagaimanakah Java antara muka dengan platform operasi dan penyelenggaraan automatik Ansible?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

AI Hentai Generator
Menjana ai hentai secara percuma.

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas



Panduan Nombor Sempurna di Jawa. Di sini kita membincangkan Definisi, Bagaimana untuk menyemak nombor Perfect dalam Java?, contoh dengan pelaksanaan kod.

Panduan untuk Weka di Jawa. Di sini kita membincangkan Pengenalan, cara menggunakan weka java, jenis platform, dan kelebihan dengan contoh.

Panduan untuk Nombor Smith di Jawa. Di sini kita membincangkan Definisi, Bagaimana untuk menyemak nombor smith di Jawa? contoh dengan pelaksanaan kod.

Dalam artikel ini, kami telah menyimpan Soalan Temuduga Spring Java yang paling banyak ditanya dengan jawapan terperinci mereka. Supaya anda boleh memecahkan temuduga.

Java 8 memperkenalkan API Stream, menyediakan cara yang kuat dan ekspresif untuk memproses koleksi data. Walau bagaimanapun, soalan biasa apabila menggunakan aliran adalah: bagaimana untuk memecahkan atau kembali dari operasi foreach? Gelung tradisional membolehkan gangguan awal atau pulangan, tetapi kaedah Foreach Stream tidak menyokong secara langsung kaedah ini. Artikel ini akan menerangkan sebab -sebab dan meneroka kaedah alternatif untuk melaksanakan penamatan pramatang dalam sistem pemprosesan aliran. Bacaan Lanjut: Penambahbaikan API Java Stream Memahami aliran aliran Kaedah Foreach adalah operasi terminal yang melakukan satu operasi pada setiap elemen dalam aliran. Niat reka bentuknya adalah

Panduan untuk TimeStamp to Date di Java. Di sini kita juga membincangkan pengenalan dan cara menukar cap waktu kepada tarikh dalam java bersama-sama dengan contoh.

Kapsul adalah angka geometri tiga dimensi, terdiri daripada silinder dan hemisfera di kedua-dua hujungnya. Jumlah kapsul boleh dikira dengan menambahkan isipadu silinder dan jumlah hemisfera di kedua -dua hujungnya. Tutorial ini akan membincangkan cara mengira jumlah kapsul yang diberikan dalam Java menggunakan kaedah yang berbeza. Formula volum kapsul Formula untuk jumlah kapsul adalah seperti berikut: Kelantangan kapsul = isipadu isipadu silinder Dua jumlah hemisfera dalam, R: Radius hemisfera. H: Ketinggian silinder (tidak termasuk hemisfera). Contoh 1 masukkan Jejari = 5 unit Ketinggian = 10 unit Output Jilid = 1570.8 Unit padu menjelaskan Kirakan kelantangan menggunakan formula: Kelantangan = π × r2 × h (4

Spring Boot memudahkan penciptaan aplikasi Java yang mantap, berskala, dan siap pengeluaran, merevolusi pembangunan Java. Pendekatan "Konvensyen Lebih Konfigurasi", yang wujud pada ekosistem musim bunga, meminimumkan persediaan manual, Allo
