I'm running some commands on multiple servers and I want them to all run concurrently,
foreach($clust['hosts'] as $hostStr) {
list($host, $port) = Str::rsplit($hostStr,':',2,22);
$ssh = new \Net_SSH2($host, $port);
if(!$ssh->login($username,$key)) {
throw new \Exception("Could not connect to $username#$host:$port");
}
$connections[] = $ssh;
}
foreach($connections as $i=>$ssh) {
$ssh->exec('cd /path/to/my/project && hg up', function($str) {
echo $str;
});
echo "right after ls $i\n";
}
But this always runs sequentially. Can I tell Net_SSH2 to be non-blocking?
One thing you could probably do is to use $ssh->setTimeout(1) or $ssh->setTimeout(0.5) or something.
You could also probably do $ssh->write(...) and just not do $ssh->read().
Related
I have a PHP login system that should be built to run on both XAMPP and Docker at the same time. My database need to be localy stored.
I create my Container and Image like these:
Image: docker build -t php . Container: docker run -dp 9000:80 --name php-app php
<?php
$host = "host.docker.internal"; // need to be that or 'localhost'
$name = "test";
$user = "root";
$passwort = "";
try {
$mysql = new PDO("mysql:host=$host;dbname=$name", $user, $passwort);
}
catch (PDOException $e) {
echo "SQL Error: ".$e->getMessage();
}
?>
Where do I get the information on which system I am running to make this value dynamic?
You can check if you are inside Docker this way:
function isDocker(): bool
{
return is_file("/.dockerenv");
}
I haven't worked on windows system yet but in Linux, You can check the processes and find process execute using docker or not.
$processes = explode(PHP_EOL, shell_exec('cat /proc/self/cgroup'));
// Check process folder path and pass here
$processes = array_filter($processes);
$is_docker = true;
foreach ($processes as $process) {
if (strpos($process, 'docker') === false) {
$is_docker = false;
}
}
Then you can implement as per your need.
if($is_docker === true){
// Do something
}
We have a Jenkins pipeline script that requests approval from the user after all the preparatory steps are complete, before it actually applies the changes.
We want to add a timeout to this step, so that if there is no input from the user then the build is aborted, and are currently working on using this kind of method:
try {
timeout(time: 30, unit: 'SECONDS') {
userInput = input("Apply changes?")
}
} catch(err) {
def user = err.getCauses()[0].getUser()
if (user.toString == 'SYSTEM') { // if it's system it's a timeout
didTimeout = true
echo "Build timed out at approval step"
} else if (userInput == false) { // if not and input is false it's the user
echo "Build aborted by: [${user}]"
}
}
This code is based on examples found here: https://support.cloudbees.com/hc/en-us/articles/226554067-Pipeline-How-to-add-an-input-step-with-timeout-that-continues-if-timeout-is-reached-using-a-default-value and other places online, but I really dislike catching all errors then working out what's caused the exception using err.getCauses()[0].getUser(). I'd rather explicitly catch(TimeoutException) or something like that.
So my question is, what are the actual exceptions that would be thrown by either the approval step timing out or the userInput being false? I haven't been able to find anything in the docs or Jenkins codebase so far about this.
The exception class they are referring to is org.jenkinsci.plugins.workflow.steps.FlowInterruptedException.
Cannot believe that this is an example provided by CloudBeeds.
Most (or probably all?) other exceptions won't even have the getCauses() method which of course would throw another exception then from within the catch block.
Furthermore as you already mentioned it is not a good idea to just catch all exceptions.
Edit:
By the way: Scrolling further down that post - in the comments - there you'll find an example catching a FlowInterruptedException.
Rather old topic, but it helped me, and I've done some more research on it.
As I figured out, FlowInterruptedException's getCauses()[0] has .getUser() only when class of getCauses()[0] is org.jenkinsci.plugins.workflow.support.steps.input.Rejection. It is so only when timeout occured while input was active. But, if timeout occured not in input, getCause()[0] will contain object of another class: org.jenkinsci.plugins.workflow.steps.TimeoutStepExecution$ExceededTimeout (directly mentioning timeout).
So, I end up with this:
def is_interrupted_by_timeout(org.jenkinsci.plugins.workflow.steps.FlowInterruptedException e, Boolean throw_again=true) {
// if cause is not determined, re-throw exception
try {
def cause = e.getCauses()[0]
def cause_class = cause.getClass()
//echo("cause ${cause} class: ${cause_class}")
if( cause_class == org.jenkinsci.plugins.workflow.steps.TimeoutStepExecution$ExceededTimeout ) {
// strong detection
return true
} else if( cause_class == org.jenkinsci.plugins.workflow.support.steps.input.Rejection ) {
// indirect detection
def user = cause.getUser()
if( user.toString().equals('SYSTEM') ) {
return true
} else {
return false
}
}
} catch(org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException e_access) {
// here, we may deal with situation when restricted methods are not approved:
// show message and Jengins' admin will copy/paste and execute them only once per Jenkins installation.
error('''
To run this job, Jenkins admin needs to approve some Java methods.
There are two possible ways to do this:
1. (better) run this code in Jenkins Console (URL: /script):
import org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval;
def scriptApproval = ScriptApproval.get()
scriptApproval.approveSignature('method org.jenkinsci.plugins.workflow.steps.FlowInterruptedException getCauses')
scriptApproval.approveSignature('method org.jenkinsci.plugins.workflow.support.steps.input.Rejection getUser')
scriptApproval.save()
'''.stripIndent())
return null
}
if( throw_again ) {
throw e
} else {
return null
}
}
And now, you may catch it with something like this:
try {
...
} catch (org.jenkinsci.plugins.workflow.steps.FlowInterruptedException err) {
if( is_interrupted_by_timeout(err) ) {
echo('It is timeout!')
}
}
P.S. I agree, this is bad Jenkins design.
I'm writing a bash script with dart.
Below code create a file. but that file doesn't have 'execute' permission.
so I'm not able to execute by doing ./ex.sh.
new File('ex.sh').writeAsStringSync(script_str);
Perhaps, I need to set FileStat to file. but i'm not able to find any APIs.
Haven't tried it but what if you try:
new File('ex.sh').writeAsString(script_str).then((final File file) {
return file.stat().then((final FileStat stat) => stat.mode = 777);
});
It seems this function is not yet implemented.
See code.google.com/p/dart/issues/detail?id=15078
As workaround, just made a utility function to run chmod command.
void _runBashCommandSync(GrinderContext context, String command, {String cwd, bool log: true}) {
context.log(command);
ProcessResult result =
Process.runSync('/bin/bash', ['-c', command], workingDirectory: cwd);
if (!log) return;
if (result.stdout.isNotEmpty) {
context.log(result.stdout);
}
if (result.stderr.isNotEmpty) {
context.log(result.stderr);
}
if (result.exitCode > 0) {
context.fail("exit code ${result.exitCode}");
}
}
_runBashCommandSync(context, 'chmod 777 ex.sh');
Why this code not works ?
function teste
{
begin
{
function lala {
while ($true) {
"JJJJ" | Out-File c:\Testes\teste.txt -Append
}
}
}
process {
Start-Job -ScriptBlock {lala}
}
}
My best guess is scoping. When Start-Job runs your script block, it runs it in a different context -- one where "lala" is not defined. However, if you were to rephrase your code like so:
function Run-As-Background-Job
{
begin
{
$appendToFile = {
while ($true) {
"JJJJ" | Out-File c:\Testes\teste.txt -Append
}
}
}
process {
Start-Job -ScriptBlock $appendToFile
}
}
the background job wouldn't try to invoke a name that isn't defined -- instead, the entire script block would be passed to it and things should work.
Note, that I recommend you test without the while loop like I did, because that's going to fill up your disk rather quickly.
Also, please aim for more meaningful function and variable names when posting code. :-)
I have the included grails script that I found in some random place on the internet and it works pretty well for firing up scripts in a bootstrapped grails env. The only thing it doesn't seem to do is kick off my conf/*Bootstrap.groovy scripts like when I do run-app.
Is there another function like loadApp() and configureApp() that will do that for me?
import org.codehaus.groovy.grails.support.PersistenceContextInterceptor
Ant.property(environment: "env")
grailsHome = Ant.antProject.properties."env.GRAILS_HOME"
includeTargets << new File("${grailsHome}/scripts/Bootstrap.groovy")
target('default': "Runs scripts in the test/local directory") {
if (!args) { throw new RuntimeException("[fail] This script requires an argument - the script to run.") }
depends(configureProxy, packageApp, classpath)
classLoader = new URLClassLoader([classesDir.toURI().toURL()] as URL[], rootLoader)
Thread.currentThread().setContextClassLoader(classLoader)
loadApp()
configureApp()
def interceptor = null
def beanNames = appCtx.getBeanNamesForType(PersistenceContextInterceptor)
if (beanNames && beanNames.size() == 1) {
interceptor = appCtx.getBean(beanNames[0])
}
try {
interceptor?.init()
new GroovyScriptEngine(Ant.antProject.properties."base.dir", classLoader).run("scripts/${args}.groovy", new Binding(['appCtx':appCtx]))
interceptor?.flush()
} catch (Exception e) {
e.printStackTrace()
interceptor?.clear()
} finally {
interceptor?.destroy()
}
}
Yes, try
new BootStrap().init()