Take the 2-minute tour ×
Ask Ubuntu is a question and answer site for Ubuntu users and developers. It's 100% free, no registration required.

I have seen many softwares such as Update Manager and Synaptic Package Manager, they wait if some other program is using the /var/lib/dpkg/lock and is locked. How can we do this through the Terminal? I saw apt-get's manual but didn't find anything useful.

share|improve this question
add comment

5 Answers

up vote 11 down vote accepted

You can use the aptdcon command Manpage icon to queue up package manager tasks by communicating with aptdaemon instead of using apt-get directly.

So basically you can just do sudo aptdcon --install chromium-browser or whatever and while that command is running you can run it again but install different packages and apt-daemon will just queue them up instead of erroring out.

This is especially useful if you're doing a long upgrade or something and want to keep installing packages or if you're scripting something together and want to make sure installing things will be more reliable.

share|improve this answer
    
Yeah! This works Thankyou! :) –  Piyush Jan 28 at 11:41
add comment

You could using a polling technique:

$ time (while ps -opid= -C apt-get > /dev/null; do sleep 1; done); \
  apt-get -y install some-other-package
share|improve this answer
add comment

I made a script which does this:

#!/bin/bash

# File path to watch
LOCK_FILE='/var/lib/dpkg/lock'

# tput escape codes
cr="$(tput cr)"
clr_end="$(tput el)"
up_line="$(tput cuu 1)"

CLEAN(){
    # Cleans the last two lines of terminal output,
    # returns the cursor to the start of the first line
    # and exits with the specified value if not False

    echo -n "$cr$clr_end"
    echo
    echo -n "$cr$clr_end$up_line"
    if [[ ! "$1" == "False" ]]; then
        exit $1
    fi
}

_get_cmdline(){
    # Takes the LOCKED variable, expected to be output from `lsof`,
    # then gets the PID and command line from `/proc/$pid/cmdline`.
    #
    # It sets `$open_program` to a user friendly string of the above.

    pid="${LOCKED#p}"
    cmdline=()
    while IFS= read -d '' -r arg; do
        cmdline+=("$arg")
    done < "/proc/${pid// }/cmdline"
    open_program="     $pid : ${cmdline[@]}"
}

# Default starting value
i=0

# Checks if the file is locked, writing output to $FUSER
while LOCKED="$(lsof -F p "$LOCK_FILE" 2>/dev/null)" ; do
    # This will be true if it isn't the first run
    if [[ "$i" != 0 ]]; then
        case $(($i % 4)) in
            0 ) s='-'
                i=4
                _get_cmdline # Re-checks the command line each 4th iteration
            ;;
            1 ) s=\\ ;;
            2 ) s='|' ;;
            3 ) s='/' ;;
        esac
    else
        # Traps to clean up the printed text and cursor position
        trap "CLEAN False; trap - SIGINT ; kill -SIGINT $$" SIGINT
        trap 'CLEAN $((128+15))' SIGTERM
        trap 'CLEAN $((128+1))' SIGHUP
        trap 'CLEAN $((128+3))' SIGQUIT

        # Default starting character
        s='-'

        _get_cmdline
        echo -n "$save_cur"
    fi
    # Prints the 2nd line first so the cursor is at the end of the 1st line (looks nicer)
    echo
    echo -n "$cr$clr_end$open_program"
    echo -n "$up_line$res_cur$cr$clr_end[$s] Waiting for other package managers to finish..."
    #echo -en "$cr$clr_end[$s] Waiting for other package managers to finish..."
    #echo -en "\n$cr$clr_end$open_program$cr$up_line"
    ((i++))
    sleep 1.5
done

CLEAN False

# This allows saving the script under a different name (e.g. `apt-wait`)
# and running it. It only imitates `apt-get` if it was launched as such
if [[ "${0##*/}" == 'apt-get' ]]; then
    exec /usr/bin/apt-get "$@"
    exit $?
fi

Save the above into /usr/local/sbin/apt-get. apt-get will then wait if another instance is already running.

Alternatively, save it as /usr/local/sbin/apt-wait, example usage:

apt-wait && aptitude

which will run aptitude after the current process holding the lock has exited.

Example run:

  1. First, an apt-get command is run, (don't run this command):

    $ sudo apt-get remove apt
    
  2. Then, in another terminal, another command is run:

    $ sudo apt-get install apt
    

    It will wait for the first command to finish then run. Output while waiting:

    [/] Waiting for other package managers to finish...
          28223 : /usr/bin/apt-get remove apt
    
share|improve this answer
add comment

Only one package manager can access the package directory while using apt-get. Either you have to quit an existing one to start a new one or you have to wait for one to finish to start a new one.

The commands corresponding to synaptic search and install are respectively "apt-cache search package" and "sudo apt-get install package".

share|improve this answer
    
But how can we make it wait if other apt-get is running? –  Piyush May 5 '12 at 13:25
    
You'll have to wait manually or write a script that will start running the new apt-get once the old one is finished. But I don't understand a situation in which you would want to do that. Is there any problem manually waiting? Perhaps you could explain your situation so that we can help more. –  harisibrahimkv May 5 '12 at 13:28
2  
It will help me in the situation when like I have lots of packages to download and suddenly I got an important call and I have to go somewhere. I want to complete the download by the time I return. But right now some other program is using the apt-get so I cannot start my download. –  Piyush May 6 '12 at 9:50
add comment

As far as I know, you can select multiple packages from synaptic and also you can provide multiple packages to apt-get. So all you need to do, is to provide apt-get with all the packages you want to install, that should do the trick.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.