Skip to content
July 24, 2014 / mb

sudo asks for password even if NOPASSWD is set in /etc/sudoers

TL;DR when a script is not marked as executable and you try to run it with sudo, you don’t get the usual -bash: myScript.sh: Permission denied message, you are prompted for a password instead!

This one was very frustrating.

What I wanted to do was to make a user (let’s call him bran) able to execute a specific script (let’s call it /home/hodor/calm_down.sh) without having to provide his password, because the script will be executed by an automated tool (Jenkins).

I reached back to my earlier post about sudo, and updated the /etc/sudoers file so that its User privilege specification section looked like this:

root    ALL=(ALL) ALL
bran    ALL=(hodor)  NOPASSWD:  /home/hodor/calm_down.sh *

The last line gives user bran the ability to run /home/hodor/calm_down.sh as user hodor passing it any number of parameters (*) without having to provide his password (NOPASSWD:).

Saved it, su‘ed into bran, ran

bran@laketower:~$ sudo -u hodor /home/hodor/calm_down.sh "it's ok"

aaaaand…

[sudo] password for hodor: 

d’oh.

I checked the syntax in /etc/sudoers, and it was ok.

I checked whether any of the declarations that followed in /etc/sudoers could override the line I set for bran and hodor, none to be found.

Heck, I even put that line as the last line, so no line could override it. Nothing.

After a good hour of googling around and finding nothing, I remembered that the script is in a Git repository for which I just checked out a different branch. As it turned out, the script lost its executable bit.

So I set the executable bit again, as user hodor:

hodor@laketower:~$ chmod +x calm_down.sh
hodor@laketower:~$ logout
root@laketower:~# su - bran
bran@laketower:~$ sudo -u hodor /home/hodor/calm_down.sh "it's ok"
hodor.
bran@laketower:~$

it worked!

I’m sure there’s a legitimate security concern for this behavior, but dang! was this hard to figure out!

July 23, 2014 / mb

ForkedBooter steals window focus on Mac OS while Maven is running

This is about running Maven, specifically.

For most Java applications, any of the solutions from this question on StackOverflow should work.

It’s a matter of passing -Djava.awt.headless=true to the Java process, which can be done for all Java processes by saving that option to a variable named JAVA_TOOL_OPTIONS in your .bashrc.

That’s fine as long as you have direct control over the Java process, which is not the case with Maven.

In my case, it was the Failsafe Maven Plugin that caused that annoyance, but some were experiencing the same behavior with an old version of Surefire. The following snippet fixes both.

In your pom.xml, change your existing <plugin> definitions so that they look like this (the important lines are highlighted):

<!-- this is inside your <project><build><plugins> block -->
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>${maven.surefire.plugin.version}</version>
    <configuration>
      <includes>
        <include>**/unit/**/*Test*.java</include>
      </includes>
      <!-- prevent the annoying ForkedBooter process from stealing 
        window focus on Mac OS -->
      <argLine>-Djava.awt.headless=true</argLine>
    </configuration>
  </plugin>
  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-failsafe-plugin</artifactId>
    <version>${maven.failsafe.plugin.version}</version>
    <configuration>
      <!-- prevent the annoying ForkedBooter process from stealing 
        window focus on Mac OS -->
      <argLine>-Djava.awt.headless=true</argLine>
      <includes>
        <include>**/integration/**/*Test*</include>
      </includes>
    </configuration>
    <executions>
      <execution>
        <goals>
          <goal>integration-test</goal>
          <goal>verify</goal>
        </goals>
      </execution>
    </executions>
  </plugin>

Done!

I added this reply to stack exchange as well, but maybe this post will be easier to find (as that question already already had an accepted answer when I replied, and it doesn’t work for Maven). We’ll see!

May 25, 2014 / mb

Fix out of sync subtitles with Python!

This is an update of my old post from a couple of years ago.

After using that script quite a few times, and loving it, I decided to give it a facelift and add the one feature that I’ve been wishing it had for all this time: the option to just tell it the timestamp of the first dialog without performing any math :)

Yeah, it’s simple math, but having to use base 60 means more brain CPU time wasted (and above all, it means more time separating me from my movie!).

I also moved the code to GitHub, so you can find it here: SubSlider. And this is the direct link to the python script, for the impatient.

The old way of specifying offsets using +/- has been replaced my a more argparse-standard system of flags. Also, the new feature I mentioned above can be used by running the script like this:

python subslider.py -s 1:23,450 MySubFile.srt

assuming your subtitles file is called MySubFile.srt and assuming that the first dialog in the movie takes place at 1:23,450. This time, there’s an “interactive” dialog that asks you to choose the first line among the first 10 lines in the .srt file. I added it because sometimes you get the equivalent of opening titles in the .srt, and that doesn’t help when you’re synchronizing.

If you want to get a different number of lines, you can simply change the LINES_TO_SHOW variable at line 43 to whatever number you prefer.

As always, feel free to contribute :)

April 12, 2014 / mb

Another wallpaper changer for Gnome and Unity

The previous wallpaper changer that I wrote in Python served me well for the last 2 years, but sometimes it would get stuck with some wallpapers: of the 200 pictures I have in my wallpapers folder (mostly taken from the paper wall), some were definitely being shown more often than others. Has the script developed a taste? Probably! :)

So this time I decided to put together something very quick, but that does a better job at never showing the same picture twice before all pictures in the folder have been set as desktop background.

It comes as a single bash script, there’s no configuration file to set, it picks pictures from a single folder (whereas the Python version could use several), and it moves files to a folder called shown when setting them as desktop background. Not very elegant, but it gets the job done!

Here it is; you can set your wallpapers folder and the refresh interval at the highlighted lines.

#!/bin/bash
#
# WallpaperChanger.sh
# Copyright 2014 Michele Bonazza michele@michelebonazza.com
#
# A simple script to automatically change your wallpaper in Gnome.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

WALLPAPERS_FOLDER=/home/path/to/your/wallpapers
REFRESH_INTERVAL=$((5 * 60)) # change every 5 minutes
MODE="zoom" # one between none, centered, wallpaper, scaled, stretched, zoom, spanned

# Changes the desktop background, and moves it to the "shown" folder so that it's
# not shown again before all wallpapers in the folder have been used.
# arg1 the file name of the file to be set as new background; must be in the
#      current folder
function change_wallpaper() {
  mv $1 shown
  gsettings set org.gnome.desktop.background picture-uri file://$WALLPAPERS_FOLDER/shown/$1
  gsettings set org.gnome.desktop.background picture-options $MODE
}

# Echoes the next wallpaper to be set, picked at random among images in the
# configured folder
function get_next_wallpaper() {
  find . -maxdepth 1 -type f -name "*.png" -o -name "*.jpg" -o -name "*.gif" -o -name "*.jpeg"| shuf -n 1
}

mkdir -p $WALLPAPERS_FOLDER/shown
cd $WALLPAPERS_FOLDER

while true; do
  NEXT_WP=$(get_next_wallpaper)
  
  # have we used all wallpapers?
  if [[ "$NEXT_WP" == "" ]]; then
    # yes, chdir to shown, and move them all back to the parent folder
    cd shown
    # move them to parent folder
    find . -maxdepth 1 -type f -name "*.png" -o -name "*.jpg" -o -name "*.gif" -o -name "*.jpeg" | xargs mv -t ..
    cd ..

    # check again
    NEXT_WP=$(get_next_wallpaper)

    if [[ "$NEXT_WP" == "" ]]; then
      echo "no wallpapers found in $WALLPAPERS_FOLDER, will check again in $REFRESH_INTERVAL seconds..."
      sleep $REFRESH_INTERVAL
      continue
    fi
  fi
  
  echo "changing background to $NEXT_WP"
  change_wallpaper $NEXT_WP
  sleep $REFRESH_INTERVAL
done

As always, I’ve also added this to my pastebin.

Save it as wallpaper_changer.sh, make it executable

chmod +x wallpaper_changer.sh

and add it to your “Startup applications” list, which can be found in Ubuntu’s main menu (the one you use to log out/shut down the computer), or can be brought up from a terminal using

gnome-session-properties

Click “Add”, use whatever name you want and browse to the wallpaper_changer.sh script (wherever you’ve saved it).

Sometimes I found that “Startup applications” doesn’t work: make sure that after having added your script and closed the window you can see an entry called wallpaper_changer.sh.desktop in the output of

ls -l ~/.config/autostart

If it’s not there, remove the entry and try again (I know, I know. The alternative is to fiddle with Upstart or init.d so if you want a GUI, that’s better than nothing!)

You can also change the effect to apply to your wallpapers at line 23 in the script.

Enjoy your new desktops! :)

March 11, 2014 / mb

How long does it take for the Google Play Store to publish my app in beta?

Your mileage may vary, but it shouldn’t take significantly longer than a couple of hours. If you’re not too unlucky, it should probably take just one hour, both when you’re publishing an app for the first time, and when you’re releasing an update for an existing app.

If it’s taking significantly longer than that (I’m talking more than one day here), you may have been fooled by Google’s peculiar requirements for deployments.

This fooled me twice (so I guess, shame on me).

When you publish an app for the first time, you need to create a Google Group or a Google+ community for testers before the link to your app becomes available. If you try to access the link (even using your own Google account) without being a member of the configured group/community, you’re greeted with a 404 page.

Last time I published an app though, setting an existing Google Group for testers (one that I had configured for a different app) didn’t seem to work. When I created a new Community on Google+, it worked right away. I don’t know if I was just unlucky or if you need a dedicated Google Group for every app, but if you still get a 404 after setting up the Google Group, just try with Google+.

After you’ve become a tester for the app (by visiting your app’s page on the Play Store) it usually takes another hour or so before the APK becomes available for download.

March 8, 2014 / mb

Eclipse freezes after installing LUA development tools plugin

This was an interesting one, but surprisingly very easy to solve.

After installing the LUA tools as a plugin, Eclipse mysteriously stopped working: what happened was, I would launch Eclipse from a shortcut (I’m using Docky in Ubuntu 13.04, but as it turns out, this is irrelevant), it would show me a LUA development tools splash screen (weird), then the Eclipse workbench… and stop there.

I went on to launch Eclipse from the command line to see what was going on and… I discovered that somehow the eclipse binary had been swapped with another one called LuaDevelopmentTools. Funny thing was, the latter was actually the original eclipse binary. Also, eclipse.ini had been renamed to LuaDevelopmentTools.ini.

Solution:

cd /path/to/eclipse/install/folder
mv eclipse eclipse.bak
mv LuaDevelopmentTools eclipse
mv LuaDevelopmentTools.ini eclipse.ini
mv eclipse.back LuaDevelopmentTools

restarted from the launcher, everything works.

March 7, 2014 / mb

Run JUnit tests in order

JUnit runs test methods in whatever order it wants, which is generally fine as long as all your test methods are independent of each other. This, though, may not be the case when you’re writing integration tests, where you could have a sequence of operations like

login(credentials);
requestProject("foo");
createNewItem("bar");
logout();

in a situation like this, you always want testLogout() to run after testLogin(), and createNewItem() to run after requestProject()!

Yes, you could group everything in a single test method, but it may become huge and very hard to maintain.

Quite surprisingly, JUnit doesn’t have a built-in solution for this. You can run test methods sorted by name using the @FixMethodOrder(MethodSorters.NAME_ASCENDING) tag, but then you need to artificially name your methods so that they appear in the order you want.

I found some alternative solutions in this stackoverflow question, but they require annotating your methods with tags to specify the order in which you want them to run. What I’d like them to do is just run in the same order as they appear in the source code for the test class. Among the answers, I just found this blog post that achieves the same result as I did, only it looks somewhat more complicated (it involves writing/including several classes).

My solution is fairly simple, but there’s 2 warnings:

  1. it uses Javassist, so if you don’t want to add libraries, there’s that
  2. it only works as long as you don’t have test classes that extend other test classes, and you don’t override all @Test-annotated methods in the subclass (I’ve never done that, but I guess as tests get complicated, you may have that); this can be fixed quite easily though, you just need to add the logic for what should come first according to your needs

On with the code!

You can grab the source straight from this pastebin, or copy/paste it from here (I added the MIT License, I think it should be the most permissive.. my intent is to say “do whatever the heck you want with this code”)

/*
 * Copyright (C) <2014> <Michele Bonazza>
 * 
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

/**
 * A test runner that runs tests according to their position in the source file
 * of the test class.
 * 
 * @author Michele Bonazza
 */
public class OrderedTestRunner extends BlockJUnit4ClassRunner {

    /**
     * Creates a new runner
     * 
     * @param clazz
     *            the class being tested
     * @throws InitializationError
     *             if something goes wrong
     */
    public OrderedTestRunner(Class<?> clazz) throws InitializationError {
        super(clazz);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.junit.runners.BlockJUnit4ClassRunner#computeTestMethods()
     */
    @Override
    protected List<FrameworkMethod> computeTestMethods() {
        // get all methods to be tested
        List<FrameworkMethod> toSort = super.computeTestMethods();

        if (toSort.isEmpty())
            return toSort;

        // a map containing <line_number, method>
        final Map<Integer, FrameworkMethod> testMethods = new TreeMap<>();

        // check that all methods here are declared in the same class, we don't
        // deal with test methods from superclasses that haven't been overridden
        Class<?> clazz = getDeclaringClass(toSort);
        if (clazz == null) {
            // fail explicitly
            System.err
                    .println("OrderedTestRunner can only run test classes that"
                            + " don't have test methods inherited from superclasses");
            return Collections.emptyList();
        }

        // use Javassist to figure out line numbers for methods
        ClassPool pool = ClassPool.getDefault();
        try {
            CtClass cc = pool.get(clazz.getName());
            // all methods in toSort are declared in the same class, we checked
            for (FrameworkMethod m : toSort) {
                String methodName = m.getName();
                CtMethod method = cc.getDeclaredMethod(methodName);
                testMethods.put(method.getMethodInfo().getLineNumber(0), m);
            }
        } catch (NotFoundException e) {
            e.printStackTrace();
        }

        return new ArrayList<>(testMethods.values());
    }

    private Class<?> getDeclaringClass(List<FrameworkMethod> methods) {
        // methods can't be empty, it's been checked
        Class<?> clazz = methods.get(0).getMethod().getDeclaringClass();

        for (int i = 1; i < methods.size(); i++) {
            if (!methods.get(i).getMethod().getDeclaringClass().equals(clazz)) {
                // they must be all in the same class
                return null;
            }
        }

        return clazz;
    }
}

to use this, you need to add Javassist to your classpath; if you have a Maven project, it’s incredibly easy to do so, just add this to your POM:

<dependency>
  <groupId>javassist</groupId>
  <artifactId>javassist</artifactId>
  <version>3.12.1.GA</version>
</dependency>

and annotate your JUnit test class with @RunWith(OrderedTestRunner.class), like this:

import wherever.you.put.OrderedTestRunner;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(OrderedTestRunner.class)
public class MyTestClass {

    @Test
    public void testZero() {
        System.out.println("test zero run");
    }

    @Test
    public void testOne() {
        System.out.println("test one run");
    }
}

That’s it!

About warning 2. above, in case you have something like MyTestClass extends BaseTestClass and you have methods annotated with @Test in BaseTestClass that aren’t overridden by MyTestClass, OrderedTestRunner will just fail printing the message you can see at line 50 above on System.err. I did this because I don’t think there’s a well-defined order in that case (should all methods from the super class run first? Should that go all the way up in the class hierarchy?), so you can adjust it to fit your particular needs.

Follow

Get every new post delivered to your Inbox.

Join 51 other followers