Error exit code 1 code showing in Jenkins Consiole output ( I do not want to see it ) - shell

I have a job running in the Jenkins pipeline and the output is showing error exit code 1 because am using if statement to create NOT_BUILT in the stage. Is there any other way to not see the work error exit code 1. I do not want to use When statement but if possible to still use IF statement and have a blank stage but without this message error exit code 1 in the console output.
This is my script below :
if(route53 == 'false' ) {
catchError(buildResult: 'SUCCESS', stageResult: 'NOT_BUILT') {
sh "exit 1"
}
}
else if(route53 == 'true' && all == "Yes" ) {
catchError(buildResult: 'SUCCESS', stageResult: 'NOT_BUILT') {
sh "exit 1"
}
}
The result in the pipeline console output is showing this, the stage graphic is fine as it is showing a blank stage but the console output error code is what I really want to manipulate.
output result
+ exit 1
[Pipeline] }
[Pipeline] }
ERROR: script returned exit code 1
[Pipeline] }
ERROR: script returned exit code 1
[Pipeline] }
ERROR: script returned exit code 1
[Pipeline] }

When using declarative pipelines the NOT_BUILT state is preserved to a stage the was not executed because its when directive was evaluated as false, and there is not direct way to set it except with the catchError workaround. (btw you can control the error message by using error('Your Message') instead of exit 1)
Therefore, it is easiest to achieve using the when directive and also makes your pipeline more readable. If you insist on using if statements you can still use them inside a when directive with the generic expression option which allows you to run any groovy code and calculate the relevant Boolean value according to your needs.
So you can still use your original code and just update it to return a Boolean:
stage('Conditional stage') {
when {
expression {
if(route53 == 'false' ) {
return false
}
else if(route53 == 'true' && all == "Yes" ) {
return false
}
return true
}
}
steps {
...
}
}

Related

Bash - exit does not exit script (only subshell) [duplicate]

How would you exit out of a function if a condition is true without killing the whole script, just return back to before you called the function.
Example
# Start script
Do scripty stuff here
Ok now lets call FUNCT
FUNCT
Here is A to come back to
function FUNCT {
if [ blah is false ]; then
exit the function and go up to A
else
keep running the function
fi
}
Use:
return [n]
From help return
return: return [n]
Return from a shell function.
Causes a function or sourced script to exit with the return value
specified by N. If N is omitted, the return status is that of the
last command executed within the function or script.
Exit Status:
Returns N, or failure if the shell is not executing a function or script.
Use return operator:
function FUNCT {
if [ blah is false ]; then
return 1 # or return 0, or even you can omit the argument.
else
keep running the function
fi
}
If you want to return from an outer function with an error without exiting you can use this trick:
do-something-complex() {
# Using `return` here would only return from `fail`, not from `do-something-complex`.
# Using `exit` would close the entire shell.
# So we (ab)use a different feature. :)
fail() { : "${__fail_fast:?$1}"; }
nested-func() {
try-this || fail "This didn't work"
try-that || fail "That didn't work"
}
nested-func
}
Trying it out:
$ do-something-complex
try-this: command not found
bash: __fail_fast: This didn't work
This has the added benefit/drawback that you can optionally turn off this feature: __fail_fast=x do-something-complex.
Note that this causes the outermost function to return 1.
My use case is to run the function unless it's already running. I'm doing
mkdir /tmp/nice_exit || return 0
And then at the end of the function
rm -rf /tmp/nice_exit

What is the best possible way to read the data from a file using readFile and converting it to a List in groovy?

I'm trying to read values from text files and putting the values into the list using the below method.
def myKeys = []
new File( '/tmp/A.txt' ).eachLine { line ->
myKeys << line
}
def myValues = []
new File( '/tmp/B.txt' ).eachLine { line ->
myValues << line
}
Problem is, Jenkins doesn't allow this to run on a slave and I'm not sure how to use readFile method here because it doesn't solve the purpose. I want to create a List, which readFile couldn't do.
You can get the same result using readFile step. It reads a given file from your workspace and returns the content of the file as a string. Then you can use String.eachLine(closure) method to iterate every line and add it to the list you expect. Keep in mind one thing, however - if you want to use String.eachLine() method, you need to do it in the #NonCPS mode. Otherwise, you will get maybe a single element from the iteration at best.
Take a look at the following example:
pipeline {
agent any
stages {
stage("Read test.txt file") {
steps {
script {
final String content = readFile(file: "test.txt")
final List myKeys = extractLines(content)
echo "myKeys = ${myKeys}"
}
}
}
}
}
#NonCPS
List extractLines(final String content) {
List myKeys = []
content.eachLine { line ->
myKeys << line
}
return myKeys
}
In this example, we use simple test.text file with the following content:
$ cat test.txt
123
qwe
asd
zxc
Running this exemplary pipeline produces the following output:
Running on Jenkins in /home/wololock/.jenkins/workspace/jobA
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Read test.txt file)
[Pipeline] script
[Pipeline] {
[Pipeline] readFile
[Pipeline] echo
myKeys = [123, qwe, asd, zxc]
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS
You could use a similar approach to extract keys and values from two different files, e.g.
def myKeys = extractLines(readFile(file:"/tmp/A.txt"))
def myValues = extractLines(readFile(file:"/tmp/B.txt"))

std::process:Command not returning Err() result when using 'bash -c'

I'm trying to understand why I'm not getting an Err() result when using bash -c expression to run a command.
Here is an example and the output below. I expect out2 and out3 to be an Err() but out3 is an Ok() with the failed status.
I'm using bash -c to execute a command from a given string, which is easy.
It's possible to get an Err() result using bash -c syntax?
#![allow(unused)]
use std::process::{Command, Output};
fn main() {
let out1 = Command::new("bash").arg("-c").arg("ls").output();
println!("out1: {:?}", out1);
let out2 = Command::new("wrongcommand").arg("-c").arg("ls").output();
println!("out2: {:?}", out2);
let out3 = Command::new("bash").arg("-c").arg("wrongcommand").output();
println!("out3: {:?}", out3);
}
Output:
out1: Ok(Output { status: ExitStatus(ExitStatus(0)), stdout: "Cargo.lock\nCargo.toml\ncrate-information.json\nsrc\ntarget\n", stderr: "" })
out2: Err(Os { code: 2, kind: NotFound, message: "No such file or directory" })
out3: Ok(Output { status: ExitStatus(ExitStatus(32512)), stdout: "", stderr: "bash: wrongcommand: command not found\n" })
I tried from command line and
$ bash -c wrongcommand
and
$ wrongcommand
and both return the same exit code (127). That's why I expected that Command failed in the same way.
That can be explained pretty easily. Follow along on the list of error codes
out1 is Ok for obvious reasons
out2 is an Err type because Command directly looked for the process, could not find it, and returned ENOENT (code 2). This error happened within rust, nothing was actually executed.
out3 is Ok because the process that Command ran is bash, and it returned its status. In this case, it wouldn't have found the command, so by bash statuses, it'll have returned 127. However, it's not that easy, because there is an additional layer of information contained in ExitStatus. On unix, when a process fails, it actually returns a 16bit/32bit integer (based on platform/libc/etc), separated in two:
The highest bits are what signal triggered the return
The lowest 8 bits are the return status of the process
And, to no surprise, if we shift 32512 8 bits to the right (it was an u16), we get... 127!
The takeaway is simple:
Err definitely means the process didn't run
Ok means the main process ran, but you'll need to check ExitStatus::success() to confirm that it actually did (i.e. 0 as exit status)
You could recover it like so:
Command::new("bash").arg("-c").arg("wrongcommand").output().and_then(|r| match r.status.success() {
true => Ok(r),
false => Err(io::Error::new(io::ErrorKind::InvalidData, "Process error"))
});
You can play with this on the playground. success() is a decently reliable indicator of child process success; all it does is check if the least significant 8 bits of the exit status is non-zero.
Obviously, this does not help if a process returns non-zero on success, but that's a different problem.

execute bash command in a gradle function

I want to create a generic function in gradle that executes a command. This function is called from a task.
The function executeCommand is triggered from the task copyFile but it seems that the commandLine commands are not executed. I did this because I need a generic ececuteCommand functionality that is triggered from multiple jobs.
def executeCommand(execCmd) {
try {
exec {
println("execute $execCmd in .")
commandLine 'bash', '-c', "ls -la"
commandLine 'bash', '-c', "${execCmd}"
}
}
catch(Exception e){
println("Exception: $e")
}
}
task copyFile {
doLast {
if(project.hasProperty('file')) {
ext.myFile = file
def execCmd="cp ${myFile} ."
executeCommand(${execCmd})
}
else {
println("Please specifiy argument files -Pfile=SRC_PATH")
}
}
}
There is a syntax error in your script, you should normally have an error as follows during execution:
* What went wrong:
Execution failed for task ':copyFile'.
> Could not find method $() for arguments [build_djiuilz6w3giaud8hgmf0oze7$_run_closure2$_closure5$_closure6#57fdda61] on task ':copyFile' of type org.gradle.api.DefaultTask. (normally you should have an error when trying to execute it : **
you need to replace the following statement in your copyFile.doLast{ } block:
executeCommand(${execCmd})
with:
executeCommand( execCmd)
// or: executeCommand( "${execCmd}" )
NOTE: in the exec {} block of your executeCommand function, there are two calls to commandLine function: only the second one will have effect so the command 'ls -al' will never be executed.
The rest of your script seems valid and should work as expected.

C - passing an unknown command into execvp()

I'm writing a fake shell, where I create a child process and then call execvp(). In the normal shell, when I enter an unknown command such as 'hello' it returns 'hello: Command not found.' However, when I pass hello into execvp(), it doesn't return any error by default and just continues running the rest of my program like nothing happened. What's the easiest way to find out if nothing was actually run? here's my code:
if(fork() == 0)
{
execvp(cmd, args);
}
else
{
int status = 0;
int corpse = wait(&status);
printf(Child %d exited with a status of %d\n", corpse, status);
}
I know that if corpse < 0, then it's an unknown command, but there are other conditions in my code not listed where I don't want to wait (such as if & is entered at the end of a command). Any suggestions?
All of the exec methods can return -1 if there was an error (errno is set appropriately). You aren't checking the result of execvp so if it fails, the rest of your program will continue executing. You could have something like this to prevent the rest of your program from executing:
if (execvp(cmd, args) == -1)
exit(EXIT_FAILURE);
You also want to check the result of fork() for <0.
You have two independent concerns.
1) is the return value of execvp. It shouldn't return. If it does there is a problem. Here's what I get execvp'ing a bad command. You don't want to wait if execvp fails. Always check the return values.
int res = execvp(argv[1], argv);
printf ("res is %i %s\n", res, strerror(errno));
// => res is -1 No such file or directory
2) The other concern is background processes and such. That's the job of a shell and you're going to need to figure out when your program should wait immediately and when you want to save the pid from fork and wait on it later.

Resources