How to trigger system exit with a given return code and Feature request
See original GitHub issueDear,
Firstly, thanks for your awesome library.
I would like to follow as much as possible standard return type on *NIX . Thus I defined some constants (see below ) and use picocli through a Runnable
class .
In order to capture exception throw by picocli I invoke CommandLine.populateCommand
method followed by App.run
. And inside the run method I can do some checks on both options and parameters and return an error code if it is needed.
But I fail to catch MissingParameterException and seem to be consumed by CommandLine::handleParseException
and CommandLine::internalHandleParseException
So what is the recommended way to capture all errors events in order to exit with the proper system exit code ?
Any improvement of the current library in order to ease custom/standard status code usage is welcome.
@CommandLine.Command(name = "Foo")
public final class App implements Runnable {
@CommandLine.Option(names = {"-v", "--verbose"}, description = "Turn-on informative messages. " +
"Multiple -v options increase the verbosity.")
private boolean[] verbose = new boolean[0];
@CommandLine.Parameters(index = "0", paramLabel = "Input", description = "Input to load.")
private File input;
@CommandLine.Parameters(index = "1", paramLabel = "LOG DIR", description = "Directory to store log files.")
private File logDir;
public static void exit(final int status) {
new Thread("App-exit") {
@Override
public void run() {
System.exit(status);
}
}.start();
}
public static void main(final String[] args) {
// Configure the number of columns used for the help message
int width = Integer.parseInt(System.getProperty("picocli.usage.width", String.valueOf(DEFAULT_USAGE_WIDTH)));
System.setProperty("picocli.usage.width", String.valueOf(width));
try {
final App app = CommandLine.populateCommand(new App(), args);
app.run();
}
catch (CommandLine.MissingParameterException e){
System.err.printf("Error missing parameter: %s%n%n", e.getMessage());
CommandLine.usage(new App(), System.err);
exit(SysExit.USAGE);
}
catch (CommandLine.ParameterException e){
System.err.printf("Error: %s%n%n", e.getMessage());
CommandLine.usage(new App(), System.err);
exit(SysExit.USAGE);
}
catch (Exception e){
System.err.printf("Unknown Error: %s%n%n", e.getMessage());
CommandLine.usage(new App(), System.err);
exit(SysExit.USAGE);
}
}
@Override
public void run() {
if (!model.exists()) {
System.err.printf("The file " + input+ " do not exists!%n%n");
new CommandLine(this).usage(System.err);
exit(SysExit.IO_ERROR);
} else if (!model.isFile()) {
System.err.printf("The item " + input+ " is not a file!%n%n");
new CommandLine(this).usage(System.err);
exit(SysExit.USAGE);
}
else if( model == null ) {
System.err.printf("Missing required parameter: INPUT%n%n");
new CommandLine(this).usage(System.err);
exit(SysExit.USAGE);
}
if (!logDir.exists()) {
System.err.printf("The directory " + logDir + " do not exists!%n%n");
new CommandLine(this).usage(System.err);
exit(SysExit.IO_ERROR);
} else if (!logDir.isDirectory()) {
System.err.printf("The item " + logDir + " is not a directory!%n%n");
new CommandLine(this).usage(System.err);
exit(SysExit.USAGE);
}
else if( logDir == null ) {
System.err.printf("Missing required parameter: LOG DIR!%n%n");
new CommandLine(this).usage(System.err);
exit(SysExit.USAGE);
}
final Logger root = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
switch (verbose.length) {
case 0:
root.setLevel(Level.OFF);
case 1:
root.setLevel(Level.INFO);
case 2:
root.setLevel(Level.WARN);
case 3:
root.setLevel(Level.DEBUG);
default:
root.setLevel(Level.DEBUG);
}
}
}
// FROM /usr/include/sysexits.h
public final class SysExit {
public static final int OK = 0;
public static final int GENERIC_ERROR = 1;
public static final int BASE = 64;
public static final int USAGE = 64;
public static final int NO_DATA = 65;
public static final int NO_INPUT = 66;
public static final int NO_USER = 67;
public static final int NO_HOST = 68;
public static final int UNAVAILLABLE = 69;
public static final int SOFTWARE = 70;
public static final int OS_ERROR = 71;
public static final int OS_FILE = 72;
public static final int CAN_NOT_CREATE = 73;
public static final int IO_ERROR = 74;
public static final int TEMP_FAIL = 75;
public static final int PROTOCOL = 76;
public static final int NO_PERM = 77;
public static final int CONFIG = 78;
}
Thanks for your insight
Issue Analytics
- State:
- Created 5 years ago
- Comments:14 (8 by maintainers)
@gerardbosch Would you mind creating a new ticket?
Yes I’m also not 100% happy about exit code handling as it stands. I don’t have a good answer on how to fix it yet, need to think about this more.