Aprenda a executar e monitorar scripts de shell com eficiência com suporte de sudo, diretórios de trabalho e controle completo de log.
Neste artigo, mergulharemos profundamente em como os usos de Dolphinscheduler ProcessBuilder
Para executar comandos de shell. Por padrão, Dolphinscheduler envolve scripts de shell usando BashShellInterceptorBuilder
Gerando comandos de execução que suportam os modos padrão e sudo.
Também vamos caminhar por um Botagem da primavera Exemplo mostrando como configurar os diretórios de trabalho, mesclar fluxos de saída, monitorar a execução do processo e os logs de saída – ajudando você a obter gerenciamento e agendamento de tarefas da concha eficientes.
1. Como Dolphinscheduler usa o ProcessBuilder
1.1. Comandos de shell de embrulho
Em Dolphinscheduler, o embrulho de comando acontece dentro:
org.apache.dolphinscheduler.plugin.process.api.shell.ShellInterceptorBuilderFactory
public class ShellInterceptorBuilderFactory {
non-public closing static String INTERCEPTOR_TYPE = PropertyUtils.getString("shell.interceptor.sort", "bash");
@SuppressWarnings("unchecked")
public static IShellInterceptorBuilder newBuilder() {
// Default logic
if (INTERCEPTOR_TYPE.equalsIgnoreCase("bash")) {
return new BashShellInterceptorBuilder();
}
if (INTERCEPTOR_TYPE.equalsIgnoreCase("sh")) {
return new ShShellInterceptorBuilder();
}
if (INTERCEPTOR_TYPE.equalsIgnoreCase("cmd")) {
return new CmdShellInterceptorBuilder();
}
throw new IllegalArgumentException("Unsupported shell sort: " + INTERCEPTOR_TYPE);
}
}
✅ Por padrão, BashShellInterceptorBuilder
é usado.
Aqui está a parte relevante:
org.apache.dolphinscheduler.plugin.process.api.shell.bash.BashShellInterceptorBuilder
public class BashShellInterceptorBuilder
extends BaseLinuxShellInterceptorBuilder {
@Override
public BashShellInterceptorBuilder newBuilder() {
return new BashShellInterceptorBuilder();
}
@Override
public BashShellInterceptor construct() throws FileOperateException, IOException {
// Core half: Generate shell script
generateShellScript();
Checklist bootstrapCommand = generateBootstrapCommand();
// Instantiate BashShellInterceptor
return new BashShellInterceptor(bootstrapCommand, shellDirectory);
}
@Override
protected String shellInterpreter() {
return "bash";
}
@Override
protected String shellExtension() {
return ".sh";
}
@Override
protected String shellHeader() {
return "#!/bin/bash";
}
}
A geração de comando acontece aqui:
org.apache.dolphinscheduler.plugin.process.api.shell.BaseLinuxShellInterceptorBuilder#generateBootstrapCommand
protected Checklist generateBootstrapCommand() {
if (sudoEnable) {
// sudo -u tenant -i /decide/xx.sh
return bootstrapCommandInSudoMode();
}
// bash /decide/xx.sh
return bootstrapCommandInNormalMode();
}
Dois caminhos:
- Modo regular (
bash /path/to/script.sh
) - Modo sudo (
sudo -u tenant -i /path/to/script.sh
)
Exemplo do modo sudo:
non-public Checklist bootstrapCommandInSudoMode() {
Checklist bootstrapCommand = new ArrayList<>();
bootstrapCommand.add("sudo");
if (StringUtils.isNotBlank(runUser)) {
bootstrapCommand.add("-u");
bootstrapCommand.add(runUser);
}
bootstrapCommand.add("-i");
bootstrapCommand.add(shellAbsolutePath().toString());
return bootstrapCommand;
}
1.2. Executando o comando Shell
A verdadeira execução é tratada aqui:
org.apache.dolphinscheduler.plugin.process.api.shell.BaseShellInterceptor
public summary class BaseShellInterceptor implements IShellInterceptor {
protected closing String workingDirectory;
protected closing Checklist executeCommands;
protected BaseShellInterceptor(Checklist executeCommands, String workingDirectory) {
this.executeCommands = executeCommands;
this.workingDirectory = workingDirectory;
}
@Override
public Course of execute() throws IOException {
ProcessBuilder processBuilder = new ProcessBuilder();
processBuilder.listing(new File(workingDirectory)); // Set working listing (necessary for loading JARs and so on.)
processBuilder.redirectErrorStream(true); // Merge error stream into output stream
processBuilder.command(executeCommands);
log.information("Executing shell command: {}", String.be part of(" ", executeCommands));
return processBuilder.begin();
}
}
2. Exemplo prático: agendamento de concha facilitada
Vamos criar um aplicativo de inicialização simples de primavera que inicie um script de shell!
2.1. Pom.xml Dependência
org.springframework.boot
spring-boot-starter
2.6.1
2.2. Código do aplicativo de inicialização da primavera
@SpringBootApplication
public class Utility {
public static void major(String[] args) throws Exception {
SpringApplication.run(Utility.class, args);
Checklist executeCommands = new ArrayList<>();
executeCommands.add("sudo");
executeCommands.add("-u");
executeCommands.add("qiaozhanwei");
executeCommands.add("-i");
executeCommands.add("/decide/take a look at/my.sh");
ProcessBuilder processBuilder = new ProcessBuilder();
processBuilder.listing(new File("/decide/take a look at")); // Set working listing
processBuilder.redirectErrorStream(true); // Merge error output into normal output
processBuilder.command(executeCommands);
Course of course of = processBuilder.begin();
strive (BufferedReader inReader = new BufferedReader(new InputStreamReader(course of.getInputStream()))) {
String line;
whereas ((line = inReader.readLine()) != null) {
// Print every line of output
System.out.println(line);
}
} catch (Exception e) {
e.printStackTrace();
}
// Watch for 10 minutes most
boolean standing = course of.waitFor(10, TimeUnit.MINUTES);
System.out.println("Execution standing -> " + standing);
}
}
2.3. Exemplo de saída de log
Os logs mostram:
- O script do shell foi executado com sucesso
- Saídas padrão e de erro foram capturadas
- O processo terminou em 10 minutos
Trecho:
Executing shell command : sudo -u qiaozhanwei -i /decide/take a look at/my.sh
...
Job job_1694766249884_0931 accomplished efficiently
standing ->true
Course of completed with exit code 0
Pensamentos finais
Usando Dolphinscheduler + ProcessBuildervocê pode lidar com flexibilidade de execução de tarefas de concha com controle complete sobre:
- Diretórios de trabalho
- Erro/fluxos de saída padrão
- Permissões sudo
- Monitoramento de tempo limite
Esta abordagem é simplesAssim, robustoe fácil de estender -Uma habilidade obrigatória se você estiver gerenciando fluxos de trabalho baseados em conchas em massive information ou DevOps Cenários!