Làm cách nào để quản lý gói chờ nếu một phiên bản khác của APT đang chạy?


50

Tôi đã thấy nhiều phần mềm như Trình quản lý cập nhật và Trình quản lý gói Synaptic, họ chờ nếu một số chương trình khác đang sử dụng /var/lib/dpkg/lockvà bị khóa. Làm thế nào chúng ta có thể làm điều này thông qua Terminal? Tôi đã apt-getxem hướng dẫn nhưng không tìm thấy gì hữu ích.


bạn cũng có thể thực hiện một số lệnh apt-get. Thích sudo apt-get install packagename && sudo apt-get updatevà họ sẽ xảy ra tự động sau khi nhau.
Alvar

1
Điều này không làm điều đó : sudo apt-get install packagename1 packagename2 packagename3 ?
Rinzwind

(Xem unix.stackexchange.com/questions/463498/... nếu bạn đang ở trong trường hợp đặc biệt, nếu bạn đang cố gắng chờ đợi cho thời gian khởi động apt để kết thúc trên Ubuntu 18,04 trở lên)
Anon

Câu trả lời:


35

Bạn có thể sử dụng các aptdconlệnhBiểu tượng trang để xếp hàng lên nhiệm vụ quản lý gói bằng cách giao tiếp với aptdaemon thay vì sử dụng apt-get trực tiếp.

Vì vậy, về cơ bản bạn chỉ có thể làm sudo aptdcon --install chromium-browserhoặc bất cứ điều gì và trong khi lệnh đó đang chạy, bạn có thể chạy lại nhưng cài đặt các gói khác nhau và apt-daemon sẽ chỉ xếp hàng chúng thay vì lỗi.

Điều này đặc biệt hữu ích nếu bạn đang thực hiện nâng cấp lâu dài hoặc một cái gì đó và muốn tiếp tục cài đặt các gói hoặc nếu bạn đang viết kịch bản một cái gì đó với nhau và muốn đảm bảo cài đặt mọi thứ sẽ đáng tin cậy hơn.


4
Có thể aptdconđược chạy sao cho nó chấp nhận bất kỳ lời nhắc apt-get -ynào không?
Noki

4
yes | aptdcon --hide-terminal --install "package"Hide Terminal là cần thiết, đường ống khác yessẽ gây ra vấn đề.
Whitehat101 17/03/2016

1
Vấn đề với câu trả lời này là nó yêu cầu cài đặt aptdcon. Tôi đang làm việc với một kịch bản bootstrap thực hiện thiết lập ban đầu của VPS, trong đó một quá trình nền cũng đang thực hiện một số thiết lập ban đầu. Tôi không thể cài đặt aptdconcho đến khi tôi có thể làm việc xung quanh khóa.
Tên giả

2
@FakeName cho cấu hình máy chủ ban đầu, bạn có thể muốn sử dụng cloud-init: cloudinit.readthedocs.io/en/latest
Jorge Castro

1
Gói gì aptdcontrong?
ctrl-alt-delor

45

Bạn có thể thực hiện apt-getđể học cách chờ đợi nếu một trình quản lý phần mềm khác đang chạy. Một cái gì đó tương tự với hành vi từ các màn hình tiếp theo:

nhập mô tả hình ảnh ở đây

Làm thế nào tôi thực hiện nó?

Tôi tạo một tập lệnh mới có tên apt-get(trình bao bọc cho apt-get) trong /usr/local/sbinthư mục với mã bash sau bên trong:

#!/bin/bash

i=0
tput sc
while fuser /var/lib/dpkg/lock >/dev/null 2>&1 ; do
    case $(($i % 4)) in
        0 ) j="-" ;;
        1 ) j="\\" ;;
        2 ) j="|" ;;
        3 ) j="/" ;;
    esac
    tput rc
    echo -en "\r[$j] Waiting for other software managers to finish..." 
    sleep 0.5
    ((i=i+1))
done 

/usr/bin/apt-get "$@"

Đừng quên làm cho nó thực thi:

sudo chmod +x /usr/local/sbin/apt-get

Trước khi kiểm tra, kiểm tra xem mọi thứ có ổn không. Đầu ra của which apt-getlệnh nên là bây giờ /usr/local/sbin/apt-get. Lý do là: theo mặc định, /usr/local/sbinthư mục được đặt trước /usr/binthư mục trong user hoặc root PATH.


đó thực sự là một cú đánh trực tiếp vào câu hỏi của tôi cảm ơn :)
rdʒɑ

2
Làm thế nào kịch bản của bạn quản lý các phiên bản xếp chồng của apt-get? Giống như, trước khi nó kết thúc, tôi khởi chạy thêm 5 apt-get?
Braiam

@Braiam Trân trọng, tôi không biết; Tôi không phải là người thử nghiệm tốt. Bạn đã kiểm tra nó? Nếu sự cố xuất hiện, tập lệnh có thể được cải thiện bằng cách tạo khóa mới với dấu thời gian khi một phiên bản mới của tập lệnh bắt đầu (chỉ là một ví dụ - cũng có nhiều cách khác).
Radu Rădeanu

ồ hùng hồn. hoạt động như một cơ duyên với mọi thứ tôi đã ném vào nó cho đến nay! Hai ngón tay cái lên ... đây chỉ là một phần của gói: D
Eric

2
Thật hoàn hảo! Tôi đã gặp sự cố khi sử dụng AWS cloudinit để cài đặt các gói trên máy chủ mới, nhưng Ubuntu thực hiện một số aptthứ khi khởi động, vì vậy dpkglệnh của tôi không thành công do bị khóa dpkg db. Tôi đã đặt lớp lót này trong userdata trên đám mây của mình: while fuser /var/lib/dpkg/lock >/dev/null 2>&1; do sleep 1; done; dpkg -i package.debvà nó hoạt động rất tốt.
Volodymyr Smotesko

20

Ngoài sự rõ ràng &&, bạn có thể đang tìm kiếm aptdcon. Công cụ này có thể phát hiện các phiên bản khác của apt và đợi chúng kết thúc:

sudo aptdcon - nâng cấp an toàn
[/] 11% Đang chờ các nhà quản lý phần mềm khác thoát khỏi Chờ đợi năng khiếu

(Tôi đang chạy năng khiếu ở một nơi khác)

Ưu điểm của công cụ này là bạn có thể dự trữ một số hành động liên tiếp mà không phải lo lắng về những gì bạn sẽ làm tiếp theo. aptdconlà lý tưởng cho các tập lệnh không giám sát và cài đặt GUI, vì bạn có thể cho phép công cụ chạy ở chế độ nền mà không chặn giao diện của bạn.

Các hoạt động được hỗ trợ bởi aptdcon:

  • --refresh, -c: Điều này tương đương với apt-get update. Nó cập nhật danh sách gói của bạn.
  • --install, --remove, --upgrade, --purge, --downgrade. Mỗi người trong số họ làm như tên của họ nói. Tên của gói là bắt buộc. -i, -r, -u, -p: Đó là những tùy chọn tắt của tất cả ngoại trừ hạ cấp, những người không có một.
  • --safe-upgrade, --full-upgradelà các đối tác apt-getcủa 's upgrade/ dist-upgradeaptitude' s safe-upgrade/ full-upgrade. Đây không cần tham số.
  • Có một số hoạt động khác, có thể được tìm thấy trong hướng dẫn. Nhưng, đây là những người dùng quan tâm nhất aptd. Có những lựa chọn mà trùng với những gì apt-key, apt-cache, dpkglàm.

apt-getbản thân nó không hỗ trợ các phương thức như vậy (để chờ các phiên bản apt khác), vì vậy, aptdcongiải pháp ưa thích cho các trình quản lý gói của GUI: USC sử dụng aptdnhư back-end, giống như Synaptic. Giải pháp khác là packagekit, nhưng nó không hỗ trợ chức năng mà bạn đang tìm kiếm (chưa).


1
aptdcon --install /path/to/pgk.debHoạt động như thế dpkg -i, mặc dù tôi không thể tìm thấy điều này được đề cập rõ ràng trong hướng dẫn.
Whitehat101 17/03/2016

Tôi có thể sử dụng điều này trong kịch bản sau khi cài đặt trong một gói không?
Nelson Teixeira

@NelsonTeixeira tại sao bạn sẽ sử dụng điều này trong tập lệnh ppst-install? Nếu hậu cài đặt được thực thi thì rõ ràng apt đang chạy.
Braiam

Tôi muốn cài đặt sau cài đặt một số gói đặc biệt không có trong kho lưu trữ. Điều này có thể không? Tôi sẽ bao gồm chúng trong gói và sau đó tập lệnh sẽ cài đặt chúng sau khi cài đặt kết thúc.
Nelson Teixeira

@NelsonTeixeira một lần nữa, tại sao nó lại cần thiết? Các tập lệnh sau khi cài đặt chỉ chạy khi có cài đặt gói. Tôi đề nghị bạn đặt một câu hỏi thay thế và giải thích trường hợp của bạn chi tiết hơn.
Braiam

18

Một cách tiếp cận rất đơn giản sẽ là một kịch bản chờ khóa không được mở. Hãy gọi nó waitforaptvà dán nó vào /usr/local/bin:

#!/bin/sh

while sudo fuser /var/{lib/{dpkg,apt/lists},cache/apt/archives}/lock >/dev/null 2>&1; do
   sleep 1
done

Sau đó chỉ cần chạy sudo waitforapt && sudo apt-get install whatever. Bạn có thể thêm ngoại lệ vào sudoersđể cho phép bạn chạy nó mà không cần mật khẩu (bạn sẽ cần nó để apt-getkhông có lợi ích lớn).

Thật không may, điều này không xếp hàng. Cho rằng một số hoạt động của apt là tương tác ("Bạn có chắc chắn muốn xóa tất cả các gói đó không?!"), Tôi không thể thấy một cách hay xung quanh điều này ...


có thể -ygiả sử có cho tất cả các hoạt động?
Braiam

Cảm ơn bạn. Tôi nghĩ rằng tôi có thể sử dụng nó tốt hơn nếu tôi sử dụng trợ giúp bí danh.
rdʒɑ

3
Trong không chắc chắn -ylà mong muốn mặc dù.
Oli

1
Tôi không nghĩ rằng bạn muốn quấn sudo fusertrong [[ $(...) ]]. Nó trả về mã thoát không khi tệp đang được truy cập sao cho đủ.
kiri

4
Tôi đã tìm thấy giải pháp sau đây để hoàn thiện hơn, vì có một số khóa liên quan khi làm việc với apt-get: while sudo fuser /var/lib/dpkg/lock /var/lib/apt/lists/lock /var/cache/apt/archives/lock >/dev/null 2>&1; do echo 'Waiting for release of dpkg/apt locks'; sleep 5; done; sudo apt-get -yy update
Manuel Kießling

3

Bạn có thể sử dụng một kỹ thuật bỏ phiếu:

$ time (while ps -opid= -C apt-get > /dev/null; do sleep 1; done); \
  apt-get -y install some-other-package

tốt hơn để sử dụnginotify
ctrl-alt-delor

3

Tôi đã tạo một kịch bản làm điều này:

#!/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}"
    pid=`echo $pid | sed 's/[\n\r ].*//'`
    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 0.025
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

Lưu ở trên vào /usr/local/sbin/apt-get. apt-getsau đó sẽ đợi nếu một phiên bản khác đang chạy.

Ngoài ra, lưu nó dưới dạng /usr/local/sbin/apt-wait, ví dụ sử dụng:

apt-wait && aptitude

mà sẽ chạy aptitudesau khi quá trình hiện tại giữ khóa đã thoát.

Chạy ví dụ:

  1. Đầu tiên, một apt-getlệnh được chạy, ví dụ:

    $ sudo apt-get remove some_package
    
  2. Sau đó, trong một thiết bị đầu cuối khác, một lệnh khác được chạy:

    $ sudo apt-get install some_other_package
    

    Nó sẽ đợi lệnh đầu tiên kết thúc rồi chạy. Đầu ra trong khi chờ đợi:

    [/] Waiting for other package managers to finish...
          28223 : /usr/bin/apt-get remove some_package
    

1
tốt hơn để sử dụnginotify
ctrl-alt-delor

3

Thật không may, fuser không làm được gì nhiều cho bạn khi bạn đang chạy trong các vùng chứa không gian tên không đặc quyền khác nhau như lxc.

Ngoài ra, aptdcon không được cài đặt theo mặc định (ít nhất là vào ngày 18.04) và làm nền cho nhiệm vụ của bạn trong hàng đợi để bạn mất tuần tự hóa. Điều này không phải là không thể vượt qua, nhưng điều đó có nghĩa là tự động hóa của bạn cần có một số cách để tránh lỗi đàn trong apt khi cài đặt aptdcon và bạn sẽ cần có một số vòng lặp chờ cho bất cứ điều gì bạn cần để tuần tự hóa sau khi cài đặt các gói qua aptdcon trừ khi đã có một số loại cờ cho điều đó rồi.

Những gì không làm việc là đàn. Điều này cũng sẽ hoạt động trên NFS, v.v. vì nó sử dụng khóa hệ thống tệp theo cách tương tự apt, chỉ với tham số -w giây, nó sẽ đợi trên khóa của bạn thay vì ném lỗi.

Vì vậy, theo mô hình trình bao bọc, hãy thêm mô hình này dưới dạng apt-get in / usr / local / bin / và chia sẻ.

Điều này cũng có lợi ích trong việc hạn chế IO bằng cách không cho phép xử lý song song trên apt để bạn có thể để cron kích hoạt cập nhật vào nửa đêm ở mọi nơi mà không cần đập đĩa.

#!/bin/bash
exec /usr/bin/flock -w 900 -F --verbose /var/cache/apt/archives/lock /usr/bin/apt-get $@  

Một yêu cầu tính năng rất hay và đơn giản cho apt-get sẽ là cờ -w để chuyển sang khóa chặn / chờ.


apt sử dụng fcntl, không phải bầy, vì vậy điều này sẽ không hoạt động. Askubfox.com/questions/1077215/NH
Andy

Điều này hoạt động hoàn hảo và là một lựa chọn tốt hơn so với sử dụng fusernhư được hiển thị trong nhiều câu trả lời vì fuservẫn có xu hướng chạy đua giữa việc xem khóa và quá trình mục tiêu lấy lại khóa. Với flockkhóa được mua và sau đó được chuyển đến quy trình mục tiêu để nó không còn thời gian để mất khóa trong thời gian đó.
jrudolph

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.