Programmatically run commands inside the standalone shell

75 views
Skip to first unread message

Benny Lutati

unread,
May 22, 2014, 5:39:27 PM5/22/14
to crash...@googlegroups.com
Hi, I am trying to run commands programmatically on a started shell. 
In CRaSH standalone main method I saw the following code:

    CRaSH main = new CRaSH();
    InvocationMatcher<Instance<CRaSH>> matcher = main.descriptor.matcher();
    InvocationMatch<Instance<CRaSH>> match = matcher.parse(line.toString());
    match.invoke(Util.wrap(main));

which looks like it doing what i want *BUT* descriptor is private, sure I can get it using reflection but is there a better way to achieve what I want?

Benny.

Benny Lutati

unread,
May 22, 2014, 6:33:17 PM5/22/14
to crash...@googlegroups.com
I just noticed that the shell does not use the descriptor at all so I can create a new one in my code, but than i noticed that match.invoke run only instances of CRaSH.. so it seems that this is not a feasible way at all.. 

Julien Viet

unread,
May 23, 2014, 1:48:27 AM5/23/14
to crash...@googlegroups.com
I have two comments:

1/ you can create you own descriptor programmatically for CRaSH:

Descriptor descriptor = CommandFactory.DEFAULT.create(CRaSH.class)

2/ have you tried instead to instantiate the CRaSH class and call the main method directly ?

CRaSH crash = new CRaSH();
crash.main(….);

the CRaSH standalone uses nothing else more than the CLI framework for processing the arguments of the JVM.

@Command
public void main(
@Option(names= {"non-interactive"})
@Usage("non interactive mode, the JVM io will not be used")
Boolean nonInteractive,
@Option(names={"c","cmd"})
@Usage("the command mounts")
String cmd,
@Option(names={"conf"})
@Usage("the conf mounts")
String conf,
@Option(names={"p","property"})
@Usage("set a property of the form a=b")
List<String> properties,
@Option(names = {"cmd-folder"})
@Usage("a folder in which commands should be extracted")
String cmdFolder,
@Option(names = {"conf-folder"})
@Usage("a folder in which configuration should be extracted")
String confFolder,
@Argument(name = "pid")
@Usage("the optional list of JVM process id to attach to")
List<Integer> pids) throws Exception {

...
}

that would provide you a much more usable interface than the mere String line.

Julien Viet
julienviet.com
> --
> Vous recevez ce message, car vous êtes abonné au groupe Google Groupes "CRaSH User Group".
> Pour vous désabonner de ce groupe et ne plus recevoir d'e-mails le concernant, envoyez un e-mail à l'adresse crash-users...@googlegroups.com (mailto:crash-users...@googlegroups.com).
> Pour obtenir davantage d'options, consultez la page https://groups.google.com/d/optout.



Benny Lutati

unread,
May 23, 2014, 6:47:50 AM5/23/14
to crash...@googlegroups.com
Thank you for your response, I am still investigating the internals of the shell so i hope the following will make sense.. 

my use-case is setting up an initial environment for new shells: reading a file (something like bashrc) with a set of commands and executed them line by line. 

about your first comment 
the method match.invoke seems to run the command itself, what I wanted is to insert the commands into the shell so that the user will be able to see them like he was writing them himself.. 
from the code it seems that the only way to do so is modifying the input stream entered into the ConsoleReader, although it not looks like the way to go.. 

about your second comment, 
you are right for simple commands but if I wanted to do something like 

"cmd1 a b c | cmd2 x | cmd3" 

then it became a little bit more complex as the commands assumes some framework services that I cannot provide for them.. 

when I thinking about it, this is actually looking like I need to add simple scripting invocation support to the shell, I remember reading in the documentation that such support not exists, should I fork the project and attempt to add one? if so any ideas where is best to start?

Benny.

> Pour vous désabonner de ce groupe et ne plus recevoir d'e-mails le concernant, envoyez un e-mail à l'adresse crash-users...@googlegroups.com (mailto:crash-users+unsub...@googlegroups.com).

Julien Viet

unread,
May 23, 2014, 7:38:20 AM5/23/14
to crash...@googlegroups.com
how will your user use crash ? as an external tool ? or inside crash ?

Julien Viet
julienviet.com
> > julienviet.com (http://julienviet.com)
> >
> >
> > On Friday 23 May 2014 at 00:33, Benny Lutati wrote:
> >
> > > I just noticed that the shell does not use the descriptor at all so I can create a new one in my code, but than i noticed that match.invoke run only instances of CRaSH.. so it seems that this is not a feasible way at all..
> > >
> > >
> > > On Friday, May 23, 2014 12:39:27 AM UTC+3, Benny Lutati wrote:
> > > > Hi, I am trying to run commands programmatically on a started shell.
> > > > In CRaSH standalone main method I saw the following code:
> > > >
> > > > CRaSH main = new CRaSH();
> > > > InvocationMatcher<Instance<CRaSH>> matcher = main.descriptor.matcher();
> > > > InvocationMatch<Instance<CRaSH>> match = matcher.parse(line.toString());
> > > > match.invoke(Util.wrap(main));
> > > >
> > > >
> > > > which looks like it doing what i want *BUT* descriptor is private, sure I can get it using reflection but is there a better way to achieve what I want?
> > > >
> > > > Benny.
> > >
> > >
> > > --
> > > Vous recevez ce message, car vous êtes abonné au groupe Google Groupes "CRaSH User Group".
> > > Pour vous désabonner de ce groupe et ne plus recevoir d'e-mails le concernant, envoyez un e-mail à l'adresse crash-users...@googlegroups.com (javascript:) (mailto:crash-users...@googlegroups.com (javascript:)).
> > > Pour obtenir davantage d'options, consultez la page https://groups.google.com/d/optout.
> >
>
> --
> Vous recevez ce message, car vous êtes abonné au groupe Google Groupes "CRaSH User Group".
> Pour vous désabonner de ce groupe et ne plus recevoir d'e-mails le concernant, envoyez un e-mail à l'adresse crash-users...@googlegroups.com (mailto:crash-users...@googlegroups.com).

Benny Lutati

unread,
May 23, 2014, 8:01:03 AM5/23/14
to crash...@googlegroups.com
inside a standalone crash that is loaded by a different program, 

I implemented a very simple ObjectFileSystem (file system that can also mount in memory objects like maps, lists, pojos (singletons for example), etc.)
when crash starts it loads the ObjectFileSystem and mount into root (/) the current directory. this was simple to achieve.
now I wish that it will look for a file that called /home/crashrc (support for different users is not planed yet) and run the commands that stored in this file. 

Example file:
mkdir /app
mount /app pack.name.Singleton.get() <more mount-arguments>
chdir /home

the only problem is that I cannot run a bash command lines programmatically...
> > > Pour vous désabonner de ce groupe et ne plus recevoir d'e-mails le concernant, envoyez un e-mail à l'adresse crash-users...@googlegroups.com (javascript:) (mailto:crash-users+unsub...@googlegroups.com (javascript:)).  
> > > Pour obtenir davantage d'options, consultez la page https://groups.google.com/d/optout.  
> >  
>  
> --  
> Vous recevez ce message, car vous êtes abonné au groupe Google Groupes "CRaSH User Group".
> Pour vous désabonner de ce groupe et ne plus recevoir d'e-mails le concernant, envoyez un e-mail à l'adresse crash-users...@googlegroups.com (mailto:crash-users+unsub...@googlegroups.com).

Julien Viet

unread,
May 24, 2014, 3:10:43 AM5/24/14
to crash...@googlegroups.com
I think we can reasonably implement the some part in crash itself.

I.e provide a org.crsh.lang.spi.Compiler for the org.crsh.lang.impl.script.ScriptLanguage that would compile a specific extension like “.sh”, this would sequentially execute the lines of the entire file as they would be entered by the shell.

This I think would make easier for you then to execute a single .sh script as the shell would take care of it.

What do you think ?

Julien Viet
julienviet.com


On Friday 23 May 2014 at 14:01, Benny Lutati wrote:

> inside a standalone crash that is loaded by a different program,
>
> I implemented a very simple ObjectFileSystem (file system that can also mount in memory objects like maps, lists, pojos (singletons for example), etc.)
> when crash starts it loads the ObjectFileSystem and mount into root (/) the current directory. this was simple to achieve.
> now I wish that it will look for a file that called /home/crashrc (support for different users is not planed yet) and run the commands that stored in this file.
>
> Example file:
> mkdir /app
> mount /app pack.name.Singleton.get() <more mount-arguments>
> chdir /home
>
> the only problem is that I cannot run a bash command lines programmatically...
>
> On Friday, May 23, 2014 2:38:20 PM UTC+3, Julien Viet wrote:
> > how will your user use crash ? as an external tool ? or inside crash ?
> >
> > Julien Viet
> > > > julienviet.com (http://julienviet.com) (http://julienviet.com)
> > > >
> > > >
> > > > On Friday 23 May 2014 at 00:33, Benny Lutati wrote:
> > > >
> > > > > I just noticed that the shell does not use the descriptor at all so I can create a new one in my code, but than i noticed that match.invoke run only instances of CRaSH.. so it seems that this is not a feasible way at all..
> > > > >
> > > > >
> > > > > On Friday, May 23, 2014 12:39:27 AM UTC+3, Benny Lutati wrote:
> > > > > > Hi, I am trying to run commands programmatically on a started shell.
> > > > > > In CRaSH standalone main method I saw the following code:
> > > > > >
> > > > > > CRaSH main = new CRaSH();
> > > > > > InvocationMatcher<Instance<CRaSH>> matcher = main.descriptor.matcher();
> > > > > > InvocationMatch<Instance<CRaSH>> match = matcher.parse(line.toString());
> > > > > > match.invoke(Util.wrap(main));
> > > > > >
> > > > > >
> > > > > > which looks like it doing what i want *BUT* descriptor is private, sure I can get it using reflection but is there a better way to achieve what I want?
> > > > > >
> > > > > > Benny.
> > > > >
> > > > >
> > > > >
> > > > > --
> > > > > Vous recevez ce message, car vous êtes abonné au groupe Google Groupes "CRaSH User Group".
> > > > > Pour vous désabonner de ce groupe et ne plus recevoir d'e-mails le concernant, envoyez un e-mail à l'adresse crash-users...@googlegroups.com (javascript:) (mailto:crash-users...@googlegroups.com (javascript:) (javascript:)).
> > > > > Pour obtenir davantage d'options, consultez la page https://groups.google.com/d/optout.
> > > >
> > > >
> > >
> > >
> > > --
> > > Vous recevez ce message, car vous êtes abonné au groupe Google Groupes "CRaSH User Group".
> > > Pour vous désabonner de ce groupe et ne plus recevoir d'e-mails le concernant, envoyez un e-mail à l'adresse crash-users...@googlegroups.com (javascript:) (mailto:crash-users...@googlegroups.com (javascript:)).
> > > Pour obtenir davantage d'options, consultez la page https://groups.google.com/d/optout.
> >
>
> --
> Vous recevez ce message, car vous êtes abonné au groupe Google Groupes "CRaSH User Group".
> Pour vous désabonner de ce groupe et ne plus recevoir d'e-mails le concernant, envoyez un e-mail à l'adresse crash-users...@googlegroups.com (mailto:crash-users...@googlegroups.com).

Benny Lutati

unread,
May 24, 2014, 7:50:40 AM5/24/14
to crash...@googlegroups.com
This sound good, but i left with the problem of forcing CRaSH to call such a script on initialization - maybe an "exec" method that will be available as part of the commands api?
e.g.,

class cmd extends BaseCommand {

    @Command 
    public void main(){
        Iterable<Object> results = exec("some command here | some other command");
    }
}

If this API will be available to the login command then I will be able to run the script on start.
Note that this is also will allow to write a command mimicking the "sh" command, so that when CRaSH will attempt to run a script "script.sh" it will actually just run "sh script.sh", this will also allow programmers to extend/replace the "sh" command.

Is this sound reasonable?

On Friday, May 23, 2014 12:39:27 AM UTC+3, Benny Lutati wrote:

Julien Viet

unread,
May 24, 2014, 1:43:34 PM5/24/14
to crash...@googlegroups.com
there is already such mechanism with login.groovy and logout.groovy.

given that a groovy script can call other commands (http://www.crashub.org/beta/reference.html#_inter_command_api) that should work already.

Julien Viet
julienviet.com


On Saturday 24 May 2014 at 13:50, Benny Lutati wrote:

> This sound good, but i left with the problem of forcing CRaSH to call such a script on initialization - maybe an "exec" method that will be available as part of the commands api?
> e.g.,
>
> class cmd extends BaseCommand {
>
> @Command
> public void main(){
> Iterable<Object> results = exec("some command here | some other command");
> }
> }
>
> If this API will be available to the login command then I will be able to run the script on start.
> Note that this is also will allow to write a command mimicking the "sh" command, so that when CRaSH will attempt to run a script "script.sh (http://script.sh)" it will actually just run "sh script.sh (http://script.sh)", this will also allow programmers to extend/replace the "sh" command.
>
> Is this sound reasonable?
>
> On Friday, May 23, 2014 12:39:27 AM UTC+3, Benny Lutati wrote:
> > Hi, I am trying to run commands programmatically on a started shell.
> > In CRaSH standalone main method I saw the following code:
> >
> > CRaSH main = new CRaSH();
> > InvocationMatcher<Instance<CRaSH>> matcher = main.descriptor.matcher();
> > InvocationMatch<Instance<CRaSH>> match = matcher.parse(line.toString());
> > match.invoke(Util.wrap(main));
> >
> >
> > which looks like it doing what i want *BUT* descriptor is private, sure I can get it using reflection but is there a better way to achieve what I want?
> >
> > Benny.
>
Reply all
Reply to author
Forward
0 new messages