137

I want to execute Linux shell commands with Maven. Here is what I tried:

<plugin>  
  <groupId>org.codehaus.mojo</groupId> 
  <artifactId>exec-maven-plugin</artifactId> 
  <version>1.1.1</version> 
  <executions>
    <execution>
      <goals>
        <goal>exec</goal> 
      </goals>
    </execution>
  </executions>
  <configuration>
    <executable>hostname</executable> 
  </configuration>
</plugin>
Lii
  • 11,553
  • 8
  • 64
  • 88
NareshKumar
  • 1,609
  • 3
  • 16
  • 13
  • please clean your question and format the pom.xml in your question. Its not readable. – zengr Aug 16 '10 at 09:30
  • 15
    I don't mean to be rude but you really need to learn how to ask questions, we are not psychic. What did you do? What did you get? What is the expected result? – Pascal Thivent Aug 16 '10 at 14:18
  • 5
    No offense @PascalThivent, but those who know Maven and pom.xml know what the OP would be referring to. :) So if someone wouldn't know Maven or pom.xml, then they should probably skip the question. It was quite obvious for me, and probably the many who liked the question. – Raid Aug 28 '20 at 10:39

7 Answers7

170

Here's what's been working for me:

<plugin>
  <artifactId>exec-maven-plugin</artifactId>
  <groupId>org.codehaus.mojo</groupId>
  <executions>
    <execution><!-- Run our version calculation script -->
      <id>Version Calculation</id>
      <phase>generate-sources</phase>
      <goals>
        <goal>exec</goal>
      </goals>
      <configuration>
        <executable>${basedir}/scripts/calculate-version.sh</executable>
      </configuration>
    </execution>
  </executions>
</plugin>

Keppil
  • 45,603
  • 8
  • 97
  • 119
Curtis
  • 3,931
  • 1
  • 19
  • 26
  • 14
    I'd like to add that this doesn't work with (at least) version 1.5.0 of the plugin, since `` should follow after `` and not be placed therein. Took me quite a while to find this simple syntactical mistake. Maven's error output is really not that helpful. – joergl Aug 29 '16 at 08:23
  • 1
    What phase or goal do we need to provide if we want to run the script after deployment phase?? – Lucy Dec 30 '16 at 10:17
  • 4
    Maven phases are listed here: https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html#Lifecycle_Reference – Ed Randall Apr 18 '17 at 17:59
  • 2
    Using `${basedir}/scripts/` in configuration block, instead of giving the full path in `` also might be a good idea – akn Sep 18 '17 at 19:57
  • "Permission denied", how do we set permissions from Maven? – Panu Haaramo Dec 17 '21 at 09:35
  • @akn Using `` to configure the dir which contains the ``, and let `` be the name of my script, fails my maven build. It gives the error "File not found", while the path is correct. I have to make `` contain the full path to my shell script, like `${project.build.scriptSourceDirectory}/fix.sh` to make it work . Maybe it is because it's a script, not a real executable. The rest is all good. – WesternGun Mar 18 '22 at 21:03
38

The problem here is that I don't know what is expected. With your current setup, invoking the plugin on the command line would just work:

$ mvn exec:exec
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Building Q3491937
[INFO]    task-segment: [exec:exec]
[INFO] ------------------------------------------------------------------------
[INFO] [exec:exec {execution: default-cli}]
[INFO] laptop
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
...

The global configuration is used, the hostname command is executed (laptop is my hostname). In other words, the plugin works as expected.

Now, if you want a plugin to get executed as part of the build, you have to bind a goal on a specific phase. For example, to bind it on compile:

  <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>exec-maven-plugin</artifactId>
    <version>1.1.1</version>
    <executions>
      <execution>
        <id>some-execution</id>
        <phase>compile</phase>
        <goals>
          <goal>exec</goal>
        </goals>
      </execution>
    </executions>
    <configuration>
      <executable>hostname</executable>
    </configuration>
  </plugin>

And then:

$ mvn compile
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Building Q3491937
[INFO]    task-segment: [compile]
[INFO] ------------------------------------------------------------------------
[INFO] [resources:resources {execution: default-resources}]
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /home/pascal/Projects/Q3491937/src/main/resources
[INFO] [compiler:compile {execution: default-compile}]
[INFO] Nothing to compile - all classes are up to date
[INFO] [exec:exec {execution: some-execution}]
[INFO] laptop
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
...

Note that you can specify a configuration inside an execution.

Pascal Thivent
  • 562,542
  • 136
  • 1,062
  • 1,124
  • [ERROR] BUILD ERROR [INFO] ------------------------------------------------------------------------ [INFO] One or more required plugin parameters are invalid/missing for 'exec:exec' [0] Inside the definition for plugin 'exec-maven-plugin' specify the following: ... VALUE -OR- on the command line, specify: '-Dexec.executable=VALUE' I get this error now. – NareshKumar Aug 16 '10 at 14:29
  • 2
    @gnash-85: I still have no idea of what you're doing. I used the exact snippet **you** provided and had no problem as shown above. Please update your question to show how you invoke maven (and what your current configuration is if you changed something). – Pascal Thivent Aug 16 '10 at 14:48
  • I have put the same code in a child module. And I am trying to execute the mvn exec:exec from the parent pom.xml. And i get this error. But when i individually execute it it is working. – NareshKumar Aug 17 '10 at 05:04
  • 5
    @gnash-85: That's normal. When you invoke `mvn exec:exec` on the parent, mvn will run it on all projects of the multi-module build, including the parent. But the parent pom doesn't have any configuration for the plugin that expects the `executable` to be defined, hence the error message. – Pascal Thivent Aug 17 '10 at 05:14
  • 3
    Adding to this discusion. If you specify your `configuration` inside the `execution` block, it will work if run as part of a group ( `mvn install`) but throw the `specify the following: ` error if run directly with `mvn exec:exec`. – actual_kangaroo Nov 04 '16 at 00:46
  • What phase or goal do we need to provide if we want to run the script after deployment phase?? – Lucy Dec 30 '16 at 10:18
26

Solved. The problem is, executable is working in a different way in Linux. If you want to run an .sh file, you should add the exec-maven-plugin to the <plugins> section of your pom.xml file.

<plugin>
  <artifactId>exec-maven-plugin</artifactId>
  <version>3.0.0</version>
  <groupId>org.codehaus.mojo</groupId>
  <executions>
    <execution>
      <!-- Run our version calculation script -->
      <id>Renaming build artifacts</id>
      <phase>package</phase>
      <goals>
        <goal>exec</goal>
      </goals>
      <configuration>
        <executable>bash</executable>
        <commandlineArgs>handleResultJars.sh</commandlineArgs>
      </configuration>
    </execution>
  </executions>
</plugin>
Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132
james25
  • 321
  • 5
  • 4
7

2 Options:

  1. You want to exec a command from maven without binding to any phase, you just type the command and maven runs it, you just want to maven to run something, you don't care if we are in compile/package/... Let's say I want to run npm start with maven, you can achieve it with the below:

mvn exec:exec -Pstart-node

For that you need the below maven section

  <profiles>
    <profile>
      <id>start-node</id>
      <build>
        <plugins>
          <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>exec-maven-plugin</artifactId>
            <version>1.3.2</version>
            <executions>
              <execution>
                <goals>
                  <goal>exec</goal>
                </goals>
              </execution>
            </executions>
            <configuration>
              <executable>npm</executable>
              <arguments><argument>start</argument></arguments>
            </configuration>
          </plugin>
        </plugins>
      </build>
    </profile>

  </profiles>
  1. You want to run an arbitrary command from maven while you are at a specific phase, for example when I'm at install phase I want to run npm install you can do that with:

mvn install

And for that to work you would need the below section:

  <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>exec-maven-plugin</artifactId>
    <version>1.3.2</version>
    <executions>

      <execution>
        <id>npm install (initialize)</id>
        <goals>
          <goal>exec</goal>
        </goals>
        <phase>initialize</phase>
        <configuration>
          <executable>npm</executable>
          <arguments>
            <argument>install</argument>
          </arguments>
        </configuration>
      </execution>
Tomer Ben David
  • 8,286
  • 1
  • 43
  • 24
3

Thanks! Tomer Ben David. it helped me. as I am doing pip install in demo folder as you mentioned npm install

<groupId>org.codehaus.mojo</groupId>
            <artifactId>exec-maven-plugin</artifactId>
            <version>1.3.2</version>
            <executions>
              <execution>
                <goals>
                  <goal>exec</goal>
                </goals>
              </execution>
            </executions>
            <configuration>
              <executable>pip</executable>
              <arguments><argument>install</argument></arguments>                            
             <workingDirectory>${project.build.directory}/Demo</workingDirectory>
            </configuration>
eric
  • 51
  • 5
2

This worked for me too. Later, I ended-up switching to the maven-antrun-plugin to avoid warnings in Eclipse. And I prefer using default plugins when possible. Example:

<plugin>
    <artifactId>maven-antrun-plugin</artifactId>
    <version>3.0.0</version>
    <executions>
        <execution>
            <id>get-the-hostname</id>
            <phase>package</phase>
            <configuration>
                <target>
                    <exec executable="bash">
                        <arg value="-c"/>
                        <arg value="hostname"/>
                    </exec>
                </target>
            </configuration>
            <goals>
                <goal>run</goal>
            </goals>
        </execution>
    </executions>
</plugin>
Eugene Barker
  • 111
  • 1
  • 7
2

The accepted answer does not work in 2021 with version 3.0.0. The configuration tag inside the execution tag results in a message, "The parameter 'exectuable' is missing or invalid."

The solution was to move the configuration tag outside the executions tag.

<plugin>
  <artifactId>exec-maven-plugin</artifactId>
  <groupId>org.codehaus.mojo</groupId>
  <executions>
    <execution>
      <phase>generate-sources</phase>
      <goals>
        <goal>exec</goal>
      </goals>
    </execution>
  </executions>
  <configuration>
    <id>Version Calculation</id>
    <executable>${basedir}/scripts/calculate-version.sh</executable>
  </configuration>
</plugin>
Mason T.
  • 1,567
  • 1
  • 14
  • 33