通过简单的终端方式添加和删除更新频道

通过简单的终端方式添加和删除更新频道

我知道 Ubuntu 中有一个 GUISoftware & Updates可以启用更新渠道

  • 更新
  • 建议的
  • 向后移植
  • 安全

如该截图所示:

在此处输入图片描述

我正在寻找一种简单的方法来在终端内使用以下命令执行此操作

sudo apt-add-update enable updates
sudo apt-add-update enable proposed
sudo apt-add-update enable backports
sudo apt-add-update enable security

sudo apt-add-update disable updates
sudo apt-add-update disable proposed
sudo apt-add-update disable backports
sudo apt-add-update disable security

还有一件事

sudo apt-add-update enable default

sudo apt-add-update disable default

为了更好地理解,举几个例子

  1. 一个空的sources.list

    • cat /etc/apt/sources.list

      <empty>
      
    • sudo apt-add-update enable security

      <empty>
      
  2. 一个已启用的存储库 ( main)

    • cat /etc/apt/sources.list

      deb http://archive.ubuntu.com/ubuntu wily main
      
    • sudo apt-add-update enable security

      deb http://archive.ubuntu.com/ubuntu wily main
      deb http://archive.ubuntu.com/ubuntu wily-security main
      
  3. 一行或两行中启用两个或多个存储库

    • cat /etc/apt/sources.list

      deb http://archive.ubuntu.com/ubuntu wily main universe
      

      或者

      deb http://archive.ubuntu.com/ubuntu wily main
      deb http://archive.ubuntu.com/ubuntu wily universe
      
    • sudo apt-add-update enable security

      deb http://archive.ubuntu.com/ubuntu wily main universe
      deb http://archive.ubuntu.com/ubuntu wily-security main universe
      

      或者

      deb http://archive.ubuntu.com/ubuntu wily main
      deb http://archive.ubuntu.com/ubuntu wily-security main
      deb http://archive.ubuntu.com/ubuntu wily universe
      deb http://archive.ubuntu.com/ubuntu wily-security universe
      
  4. 带有deb-src条目

    • cat /etc/apt/sources.list

      deb http://archive.ubuntu.com/ubuntu wily main universe
      deb-src http://archive.ubuntu.com/ubuntu wily main universe
      
    • sudo apt-add-update enable security

      deb http://archive.ubuntu.com/ubuntu wily main universe
      deb-src http://archive.ubuntu.com/ubuntu wily main universe
      deb http://archive.ubuntu.com/ubuntu wily-security main universe
      deb-src http://archive.ubuntu.com/ubuntu wily-security main universe
      
  5. 含有非活动deb-src条目

    • cat /etc/apt/sources.list

      deb http://archive.ubuntu.com/ubuntu wily main universe
      # deb-src http://archive.ubuntu.com/ubuntu wily main universe
      
    • sudo apt-add-update enable security

      deb http://archive.ubuntu.com/ubuntu wily main universe
      # deb-src http://archive.ubuntu.com/ubuntu wily main universe
      deb http://archive.ubuntu.com/ubuntu wily-security main universe
      
  6. 事情default

    • cat /etc/apt/sources.list

      deb http://archive.ubuntu.com/ubuntu wily-security universe
      
    • sudo apt-add-update enable default

      deb http://archive.ubuntu.com/ubuntu wily universe
      deb http://archive.ubuntu.com/ubuntu wily-security universe
      
  7. 只有一个条目和disable操作

    • cat /etc/apt/sources.list

      deb http://archive.ubuntu.com/ubuntu wily-security universe
      
    • sudo apt-add-update disable security

      <empty>
      
  8. 不同或相同的服务器用于不同或相同的存储库,尊重每个服务器

    • cat /etc/apt/sources.list

      deb http://archive.ubuntu.com/ubuntu wily universe
      deb http://us.archive.ubuntu.com/ubuntu wily main
      
    • sudo apt-add-update enable security

      deb http://archive.ubuntu.com/ubuntu wily universe
      deb http://us.archive.ubuntu.com/ubuntu wily main
      deb http://archive.ubuntu.com/ubuntu wily-security universe
      deb http://us.archive.ubuntu.com/ubuntu wily-security main
      
  9. 不同的 Ubuntu 版本适用于不同的存储库,尊重每个版本

    • cat /etc/apt/sources.list

      deb http://archive.ubuntu.com/ubuntu wily main universe
      deb http://archive.ubuntu.com/ubuntu trusty main
      
    • sudo apt-add-update enable security

      deb http://archive.ubuntu.com/ubuntu wily main universe
      deb http://archive.ubuntu.com/ubuntu trusty main
      deb http://archive.ubuntu.com/ubuntu wily-security main universe
      deb http://archive.ubuntu.com/ubuntu trusty-security main
      
  10. PPA 或其他软件包源(非规范)sources.list

    忽略!

  11. 不要更改协议,例如https,,,...httptor

答案1

我分析了Ubuntu 软件中心写的python

之后,我编写了下面的代码,运行良好。aptsources是 Ubuntu 软件中心用于管理/etc/apt/sources.list和的 Python 模块/etc/apt/sources.list.d

#!/usr/bin/python

import aptsources.sourceslist
from subprocess import Popen, PIPE
import errno

import os

def _lsb_release():
    """Call lsb_release --idrc and return a mapping."""
    result = {'Codename': 'sid', 'Distributor ID': 'Debian',
              'Description': 'Debian GNU/Linux unstable (sid)',
              'Release': 'unstable'}
    try:
        out = Popen(['lsb_release', '-idrc'], stdout=PIPE).communicate()[0]
        # Convert to unicode string, needed for Python 3.1
        out = out.decode("utf-8")
        result.update(l.split(":\t") for l in out.split("\n") if ':\t' in l)
    except OSError as exc:
        if exc.errno != errno.ENOENT:
            logging.warning('lsb_release failed, using defaults:' % exc)
    return result


if __name__ == "__main__":
    if len(os.sys.argv) != 3 or \
        os.sys.argv[1] not in ['enable', 'disable'] or \
        os.sys.argv[2] not in ['updates', 'security', 'proposed', 'backports', 'default']:
        print "Usage: apt-add-update <enable|disable> <default|updates|security|proposed|backports>"
        os.sys.exit(0)

    release = _lsb_release()
    codename = release['Codename']

    sourcelist = aptsources.sourceslist.SourcesList()

    template = None

    main_uri = ""
    main_comps = []
    main_types = []
    child_comps = []
    child_types = []

    for tmpl in sourcelist.matcher.templates:
        if tmpl.name == codename and tmpl.distribution == "Ubuntu":
            template = tmpl
            break

    updated = False

    for source in sourcelist.list:
        if source.invalid:
            continue
        for comp in source.comps:
            if comp not in child_comps:
                child_comps.append(comp)

        if source.template and source.template.official and source.dist == codename and source.template.name == codename:
            main_uri = source.uri

            for comp in source.comps:
                if comp not in main_comps:
                    main_comps.append(comp)

            main_types.append(source.type)
        else:
            child_types.append(source.type)

        if source.dist == codename + "-" + os.sys.argv[2]:
            if os.sys.argv[1] == 'enable' and source.type in main_types:
                source.set_enabled(True)
            if os.sys.argv[1] == 'disable':
                source.set_enabled(False)
            updated = True

        if source.dist == codename and os.sys.argv[2] == "default":
            if os.sys.argv[1] == 'enable' and source.type in child_types:
                source.set_enabled(True)
            if os.sys.argv[1] == 'disable':
                source.set_enabled(False)
            updated = True

    if not main_uri:
        main_uri = "http://archive.ubuntu.com/ubuntu"

    if os.sys.argv[2] == "default" and not main_comps:
        main_comps = child_comps

    if not main_comps:
        main_comps = ['main', 'restricted', 'universe', 'multiverse']

    if not updated and os.sys.argv[1] != 'disable':

        if os.sys.argv[2] == "default":
            uri = main_uri
            if tmpl.base_uri:
                uri = tmpl.base_uri

            tmpl = template
            line = tmpl.type + " " + uri + " " + tmpl.name + " " + " ".join(main_comps)

            sourceentry = aptsources.sourceslist.SourceEntry(line)
            sourcelist.list.append(sourceentry)


        for tmpl in template.children:
            if tmpl.name != codename + "-" + os.sys.argv[2] and \
                not (os.sys.argv[2] == "default" and tmpl.name == codename):
                continue

            if os.sys.argv[2] == "default" and tmpl.type not in child_types:
                continue

            if os.sys.argv[2] != "default" and tmpl.type not in main_types:
                continue

            uri = main_uri
            if tmpl.base_uri:
                uri = tmpl.base_uri
            if not uri:
                continue

            line = tmpl.type + " " + uri + " " + tmpl.name + " " + " ".join(main_comps)

            sourceentry = aptsources.sourceslist.SourceEntry(line)
            sourcelist.list.append(sourceentry)

    sourcelist.save()

使用文件名保存此代码/usr/local/bin/apt-add-update。然后按如下方式运行。

$ sudo apt-add-update <enable|disable> <default|updates|security|proposed|backports>

更新它为多发行版支持,例如trustywily

#!/usr/bin/python

import aptsources.sourceslist
import os

subdistnames = ['updates', 'security', 'proposed', 'backports']

def get_subdistname(distname):
    rc = "default"
    try:
        rc = distname.split("-")[1]
    except:
        pass
    return rc

def get_distname(distname):
    rc = distname
    try:
        rc = distname.split("-")[0]
    except:
        pass
    return rc

def duplicate_check(entries):
    new_entries = []
    for source in entries:
        for newsource in new_entries:
            if source.type == newsource.type and source.uri == newsource.uri and source.dist == newsource.dist:
                for comp in newsource.comps:
                    if comp in source.comps:
                        source.comps.remove(comp)

        if len(source.comps) > 0:
            new_entries.append(source)
    return new_entries

if __name__ == "__main__":
    if len(os.sys.argv) != 3 or \
        os.sys.argv[1] not in ['enable', 'disable'] or \
        ( os.sys.argv[2] not in subdistnames and os.sys.argv[2] != 'default' ):
        print "Usage: apt-add-update <enable|disable> <default|updates|security|proposed|backports>"
        os.sys.exit(0)

    sourcelist = aptsources.sourceslist.SourcesList()
    sourcelist.list = []
    sourcelist.load('/etc/apt/sources.list')

    main_entries = []
    child_entries = []
    other_entries = []

    distro_names = []

    for tmpl in sourcelist.matcher.templates:
        if tmpl.name.find('-') > 0 or tmpl.distribution != "Ubuntu":
            continue
        distro_names.append(tmpl.name)

    for source in sourcelist.list:
        if source.invalid or source.disabled:
            continue
        subdistname = get_subdistname(source.dist)

        if source.dist in distro_names:
            main_entries.append(source)
        elif subdistname in subdistnames:
            child_entries.append(source)
        else:
            other_entries.append(source)

    if os.sys.argv[2] in subdistnames:
        modified = True
        while modified:
            modified = False
            for source in child_entries:
                if get_subdistname(source.dist) == os.sys.argv[2]:
                    child_entries.remove(source)
                    modified = True
                    continue

        if os.sys.argv[1] == "enable":
            for source in main_entries:
                uri = source.uri
                if os.sys.argv[2] == "security":
                    uri = "http://security.ubuntu.com/ubuntu"
                comps = []
                for i in source.comps:
                    if i in ['main', 'restricted', 'universe', 'multiverse']:
                        comps.append(i)
                line = source.type + " " + uri + " " + source.dist + "-" + os.sys.argv[2] + " " + " ".join(comps)
                sourceentry = aptsources.sourceslist.SourceEntry(line)
                child_entries.append(sourceentry)

    else:
        main_entries = []
        if os.sys.argv[1] == "enable":
            for source in child_entries:
                uri = source.uri
                if get_subdistname(source.dist) == "security":
                    uri = "http://archive.ubuntu.com/ubuntu"
                comps = []
                for i in source.comps:
                    if i in ['main', 'restricted', 'universe', 'multiverse']:
                        comps.append(i)
                line = source.type + " " + uri + " " + get_distname(source.dist) + " " + " ".join(comps)
                sourceentry = aptsources.sourceslist.SourceEntry(line)
                main_entries.append(sourceentry)

    main_entries = duplicate_check(main_entries)
    child_entries = duplicate_check(child_entries)
    other_entries = duplicate_check(other_entries)

    sourcelist.list = []
    sourcelist.list.extend(main_entries)
    sourcelist.list.extend(child_entries)
    sourcelist.list.extend(other_entries)

    sourcelist.save()

参考网址为https://github.com/dupingping/apt-add-update/tree/master

答案2

2015 年 11 月 27 日更新

脚本的第二个版本仍然让我不满意,源代码过于臃肿,而且必须使用多种不同的工具。因此我尝试仅使用 AWK 重写脚本。

新脚本使用纯 AWK,并且更好地遵守了要求。本质上,它/etc/apt/sources.list每次运行时都会重写。

运行脚本后,需要更新,因此sudo apt-get update脚本成功退出后再运行。

该文件必须启用可执行权限chmod +x add-update.awk,并保存在$PATH变量中包含的任意目录中。特别建议将脚本保存到$HOME/bin文件夹(也必须将其附加到变量中$PATH)。

/etc/apt/sources.list不需要备份原始文件,但强烈建议备份。要备份文件,请执行以下操作

sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak

用法:

sudo ./add-update.awk -v ACTION=[enable|disable|help] -v SOURCE=[updates|backports|security|proposed]

来源:github

演示:

sergrep:$ cat /etc/apt/sources.list                                                                              
deb http://it.archive.ubuntu.com/ubuntu wily main universe
deb http://us.archive.ubuntu.com/ubuntu wily-backports main

deb-src http://it.archive.ubuntu.com/ubuntu wily main universe
deb-src http://us.archive.ubuntu.com/ubuntu wily-backports main
# removed

sergrep:$ sudo ./add-update.awk -v ACTION="enable" -v SOURCE="security"   
[sudo] password for xieerqi: 
/etc/apt/sources.list
<<< Script finished processing

sergrep:$ cat /etc/apt/sources.list                                                                              
deb http://it.archive.ubuntu.com/ubuntu wily main universe
deb http://it.archive.ubuntu.com/ubuntu wily-security  main universe
deb http://us.archive.ubuntu.com/ubuntu wily-backports main
deb http://us.archive.ubuntu.com/ubuntu wily-security  main
deb-src http://it.archive.ubuntu.com/ubuntu wily main universe
deb-src http://it.archive.ubuntu.com/ubuntu wily-security  main universe
deb-src http://us.archive.ubuntu.com/ubuntu wily-backports main
deb-src http://us.archive.ubuntu.com/ubuntu wily-security  main

源代码

#!/usr/bin/awk -f
#
###########################################################
# Author: Serg Kolo
# Date: Nov 27,2015
# Purpose: A script that enables/disables 4 ubuntu sources
# (namely updates, backports, proposed, and security )
# much in a way like software-properties-gtk does
# Written for:  http://paste.ubuntu.com/13434218/
###########################################################
#
# Permission to use, copy, modify, and distribute this software is hereby granted
# without fee, provided that  the copyright notice above and this permission statement
# appear in all copies.
#
# 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.

function printUsage() {
    print "Usage: sudo ./add-update.awk -v ACTION=[enable|disable|help] -v SOURCE=[updates|backports|security|proposed]";
    exit
}

function checkSourceEnabled()
{
    if ( $3 ~ SOURCE) {
        print SOURCE" is enabled; exiting"
        VAL = 1
    }
    else {
        VAL = 0
    }
    return VAL
}

function disableSource()
{
    if ( $0 ~ SOURCE ) $0="# removed";
    j++;
    newLines[j]=$0;
}

function listStuff () {
    for(k=4; k<=NF; k++) if ( $k~/#/  ) {break} else {
            COMPONENTS=COMPONENTS" "$k
        };
    gsub(/\-.*/,"",$3);
    STRING=$1" "$2" "$3APPEND" "COMPONENTS;
    COMPONENTS=""
               return STRING;
}

function replaceFile()
{
    command="mv  /tmp/sources.list "ARGV[1]
            system(command);
}

############
#  MAIN
#############
BEGIN {

# argument checking sequence
# must remain written in if-else
# structure rather than case,
# to consider users who may not be able
# to install gawk due to broken sources.list
# which is what this script should be aimed at

# actions checked first so that 
# help message can be printed 
 if ( ACTION ==  "enable" ||
      ACTION == "disable" ||
      ACTION == "default"  ) {

    print "<<< ACTION ARG OK" 
  }
  else if (ACTION == "help" ){
    printUsage()
    exit
  }


  if ( SOURCE == "update" || 
       SOURCE == "security" || 
       SOURCE == "backports" || 
       SOURCE == "proposed" ) { 
       print "<<< SOURCE ARG OK"

  }

   else if ( ACTION != "default"  || ACTION != "help" ) {  
        print "<<< E: SOURCE ARG INCORRECT"; 
        printUsage(); 
        exit 1   }

    # static filename to operate on
    ARGV[ARGC++]="/etc/apt/sources.list";

    if (ACTION == "enable" ) {
        APPEND="-"SOURCE;
    } else{
        APPEND="";
    }

} # END OF BEGIN

$0~/^deb*/ && $0!~/partner/ && $0!~/extra/ {

    if ( ACTION == "enable" ) {
        j++;
        ARRAY[j]=$0
        ENABLED=checkSourceEnabled();

        if ( ENABLED ) {
            exit 1
        }
        else {
            j++;
            ARRAY[j]=listStuff();
        }

    }
    else if ( ACTION == "disable" ){
        disableSource() ;
    }
    else if ( ACTION == "default" && SOURCE == "default" ) {
        j++;
        defaultsArray[j]=$0;
        j++;
        defaultsArray[j]=listStuff();
    }
}

END {
    print "<<< Script finished processing" ;
    if ( ACTION =="enable" && ENABLED == 0 ){
     for(i=1;i<=j;i++)
        print ARRAY[i] |  "sort -u > /tmp/sources.list ";
     replaceFile();
     }
     else if ( ACTION == "disable" ) {
       for ( i=1;i<=j;i++  ) print newLines[i] | "sort -u > /tmp/sources.list"
       replaceFile();
     }
     else if (ACTION == "default" ){
        for ( i=1;i<=j;i++  ) print defaultsArray[i] | "sort -i -u > /tmp/sources.list"
        replaceFile();
     }
}

# END OF MAIN

--

之前的版本

github 上的版本 #1(带有 AWK 和 SED 的 bash 脚本)

github 上的版本 #2(也是 bash 脚本)

答案3

用法:

## testing

apt-add-update  enable|disable  default|security|updates|proposed|backports  [file]


## real

sudo  apt-add-update  enable|disable  default|security|updates|proposed|backports

以下为要点:

我解析了该文件,因为我自己正在寻找一些其他选项。

  • 检查是否有镜像,无论是官方的(包括旧版本、端口)还是从python-apt包加载的社区提供的其他镜像(它包含一个包含所有镜像的文件)。

    /usr/share/python-apt/templates/Ubuntu.mirrors
    
  • 始终将官方 URI 保留在文件中。因此,即使禁用所有 URI,它也会保留注释行以进行持久性设置。它使用字母排序类型、url、dist、comp 将行解析为最少。

  • 如果获取输入文件作为第三个参数或者没有写入权限,则打印到标准输出/etc/apt/sources.list

  • 不支持[ options ]喜欢[ arch=amd64 ]
  • 我强制disable default用户指定要禁用的内容。
  • 我不喜欢最后一个选项(9),因为我故意混合了 repo。因此它们应该被视为第三方存储库。

下载:带有完整的测试集。

https://github.com/sneetsher/au_700860_apt_channels

脚本:

#!/usr/bin/python3

import sys,os
import re

## official repo's 

#http://ports.ubuntu.com/ubuntu-ports/
#http://old-releases.ubuntu.com/ubuntu/
#http://security.ubuntu.com/ubuntu/
#http://archive.ubuntu.com/ubuntu/

repo_official_uri_re = re.compile(r"\A(http|ftp)://(([a-zA-Z]*.)?archive|security|old-releases|ports).ubuntu.com/ubuntu(-ports)?[/]?\Z")

## load other mirrors

mirrors=[]

mir_re = re.compile(r"\A(http|ftp)://")

with open("/usr/share/python-apt/templates/Ubuntu.mirrors","r") as f:
    for l in f:
        if mir_re.match(l):
            mirrors.append(l.strip())
f.close()
#print(mirrors)

## system release

with open("/etc/lsb-release","r") as f:
    for l in f:
        k,v=l.split("=")
        if k=="DISTRIB_CODENAME":
            release = v.strip()
            break

#print(release)
f.close()

## load sources.list

##TODO: missing support deb line options like [ arch=whatever ] 
emp_re  = re.compile(r"\A\s*\Z")
repo_re = re.compile(r"\A#* *deb(-src)? *(http://|ftp://|file://|cdrom:)")
com_re  = re.compile(r"\A#")
repo_details_re = re.compile(r"\A(?P<active>#*) *(?P<type>deb(-src)?) *(?P<uri>(http://|ftp://|file://|cdrom:\[[a-zA-Z0-9 \-_().]*\])?\S*) (?P<dist>[a-zA-Z\-_]*) (?P<comp>[a-zA-Z ]*\Z)")


##example
sources={
  "http://archive.ubuntu.com/ubuntu/":{
    "active":True,
    "deb":{
      "wily":["universe","multiverse","restricted","main"],
      "wily-security":["main","restricted","universe","multiverse"]
      },
    "deb-src":{
      "wily":["universe","multiverse","restricted","main"]
      },
    "mirror":True    
    }
  }

sources={}

uri=""

##for testing
if len(sys.argv)>=4 and os.path.isfile(sys.argv[3]):
    ifile = sys.argv[3]
else:
    ifile = "/etc/apt/sources.list"

with open(ifile, "r") as f:
    for l in f:
        l=l.strip()

        r = emp_re.match(l)
        if r:
            continue
        else:
            #print("raw:",l)

            r = repo_re.match(l)
            if r:
                #print("repository:",l)
                r = repo_details_re.match(l)
                #print(r.groupdict())
                uri=r.group("uri")
                if uri[-1]!="/":
                    uri += "/"
                if (uri not in sources):
                    sources[uri] = {"active":False,"deb":{},"deb-src":{},"mirror":False}
                    m = repo_official_uri_re.match(uri)
                    if m or uri in mirrors:
                        sources[uri]["mirror"] = True
                    if r.group("active")=="":
                            sources[uri]["active"]=True
                    sources[uri][r.group("type")][r.group("dist")]=r.group("comp").split()
                else:
                    if r.group("active")=="" and sources[uri]["active"]==False:
                        sources[uri]["active"]=True
                        sources[uri]["deb"]={}
                        sources[uri]["deb-src"]={}
                        sources[uri][r.group("type")][r.group("dist")]=r.group("comp").split()
                    if (r.group("active")=="")==sources[uri]["active"]:
                        if r.group("dist") not in sources[uri][r.group("type")]:
                            sources[uri][r.group("type")][r.group("dist")]=r.group("comp").split()
                        else:
                            for c in r.group("comp").split():
                                if c not in sources[uri][r.group("type")][r.group("dist")]:
                                    sources[uri][r.group("type")][r.group("dist")].append(c)
            else:
                r = com_re.match(l)
                if r:
                    #print("comment",l)
                    continue
                else:
                    print("unknown",l)
    #print(sources)

f.close()

## process argumments

#fallback for default component to be copied from
comp=[release+"-security",release+"-update",release+"-proposed"]
found_other_comp=False 

if sys.argv[2]=="default" and sys.argv[1]=="enable":
    for u in sorted(sources.keys()):
        if sources[u]["mirror"]:
            if sources[u]["active"]:
                for t in ["deb","deb-src"]:
                    if release not in sources[u][t]:
                        for d in range(len(comp)):
                            if comp[d] in sources[u][t]:
                                other_comp_found=True
                                for i in range(d):
                                    sources[u][t][comp[i]]=sources[u][t][comp[d]]
                                sources[u][t][release]=sources[u][t][comp[d]]

                        ###don't activate any thing if commented like an empty file.
                        #if not found_other_comp and t=="deb":
                        #   sources[u][t][release]=["main"]
            #else:
            #   sources[u]["active"]=True
            #   sources[u]["deb"]={release:["main"]}
            #   sources[u]["deb-src"]={}

    ## carry on enable security
    sys.argv[2] = "security"

if sys.argv[2]=="security" or sys.argv[2]=="updates" or sys.argv[2]=="proposed" or sys.argv[2]=="backports":
    for u in sorted(sources.keys()):
        if sources[u]["mirror"] and sources[u]["active"]:
            if sys.argv[1]=="disable":
                if len(sources[u]["deb"])+len(sources[u]["deb-src"])>(release+"-"+sys.argv[2] in sources[u]["deb"])+(release+"-"+sys.argv[2] in sources[u]["deb-src"]):
                    if release+"-"+sys.argv[2] in sources[u]["deb"]:
                        del sources[u]["deb"][release+"-"+sys.argv[2]]
                    if release+"-"+sys.argv[2] in sources[u]["deb-src"]:
                        del sources[u]["deb-src"][release+"-"+sys.argv[2]]
                else:
                    sources[u]["active"] = False
            elif sys.argv[1]=="enable":
                for t in ["deb","deb-src"]:
                    if release in sources[u][t]:
                        if release+"-"+sys.argv[2] not in sources[u][t]:
                            sources[u][t][release+"-"+sys.argv[2]]=sources[u][t][release]
                        else:
                            for c in sources[u][t][release]:
                                if c not in sources[u][t][release+"-"+sys.argv[2]]:
                                    sources[u][t][release+"-"+sys.argv[2]].append(c)

## generate the new list
data_out=""
for u in sorted(sources.keys()):
    #print(u)
    for t in ["deb","deb-src"]:
        for d in sorted(sources[u][t].keys()):
            data_out += (not sources[u]["active"])*"#"+" ".join([t,u,d,""])+" ".join(sorted(sources[u][t][d]))+"\n"

if len(sys.argv)>=4 or not os.access("/etc/apt/sources.list", os.W_OK):
    print(data_out)
else:
    with open("/etc/apt/sources.list","w") as f:
        f.write(data_out)
    f.close()

sys.exit(0)

答案4

这正是所要求的;

如果有必要,我会不时更新它;

最新版本可以在这里找到GitHub 存储库

要从 GitHub 存储库安装:

  • 安装gitsudo apt-get install git
  • 克隆存储库:git clone https://github.com/kos0/addRemoveDistribution.git

概要:

enableDisableDistribution.pl <enable|disable> <default|security|updates|proposed|backports>

s1

s2

s3

#!/usr/bin/perl

sub printUsage {
    print("Usage: enableDisableDistribution.pl \e[4maction\e[0m \e[4mdistribution\e[0m\n\n");
    print("\e[4maction\e[0m must be \e[1menable\e[0m or \e[1mdisable\e[0m\n");
    print("\e[4mdistribution\e[0m must be \e[1mdefault\e[0m, \e[1msecurity\e[0m, \e[1mupdates\e[0m, \e[1mproposed\e[0m or \e[1mbackports\e[0m");
    exit(0);
}

sub parse {
    open(my $in, "/etc/apt/sources.list") || die("Couldn't open '/etc/apt/sources.list': $!");
    while(<$in>) {
        my $matchDistribution;
        chomp;
        if(/^deb(-src)? +(.*?).ubuntu.com\/ubuntu\/? +(.*?) +(.*?) *(#.*)?$/) {
            my $debSrc = $1 eq "-src";
            my $URI = $2;
            my @split = split("-", $3);
            my @components = sort(split(" ", $4));
            if(($distribution eq "default" && defined($split[1])) || ($distribution ne "default" && $split[1] ne $distribution)) {
                push(@add, "$debSrc,$URI,$split[0],@components");
            }
            else {
                $matchDistribution = 1;
            }
        }
        (! $matchDistribution && push(@notMatchDistribution, $_)) || push(@matchDistribution, $_);
    }
    close($in);
}

sub update {
    while(1) {
        print("Would you like to update the cache? Y-y/N-n: \n");
        my $update = <STDIN>;
        if($update =~ /^y$/i) {
            my $ret = system("apt-get update");
            exit($ret);
        }
        elsif($update =~ /^n$/i) {
            exit(0);
        }
        else {
            print("Please enter Y-y or N-n.\n");
        }
    }
}

sub rewrite {
    if($action eq "enable") {
        if(@matchDistribution == 0) {
            open(my $out, ">", "/etc/apt/sources.list") || die("Couldn't open '/etc/apt/sources.list': $!");
            foreach(@notMatchDistribution) {
                print $out ($_ . "\n");
            }
            foreach(@add) {
                my @x = split(",");
                my @y = split(" ", $x[3]);
                my $line = sprintf("deb%s $x[1].ubuntu.com/ubuntu $x[2]%s @y", $x[0] && sprintf("-src"), $distribution ne "default" && sprintf("-$distribution"));
                if(! grep(/^$line$/, @added)) {
                    print $out ($line . " #Added by enableDisableDistribution\n");
                    push(@added, $line);
                }
            }
            close($out);
            printf("Added %s %s.\n", scalar(@added), @added == 1 ? sprintf("entry") : sprintf("entries"));
            update;
        }
        else {
            print("$distribution is enabled already. Aborting.\n");
            exit(1);
        }
    }
    else {
        if(@matchDistribution > 0) {
            open(my $out, ">", "/etc/apt/sources.list") || die("Couldn't open '/etc/apt/sources.list': $!");
            foreach my $line (@notMatchDistribution) {
                print $out ($line . "\n");
            }
            close($out);
            printf("Removed %s %s.\n", scalar(@matchDistribution), @matchDistribution == 1 ? sprintf("entry") : sprintf("entries"));
            update;
        }
        else {
            print("$distribution is disabled already. Aborting.\n");
            exit(1);
        }
    }
}

if($> != 0) {
    print("You must be root to run enableDisableDistribution.\n");
    exit(1);
}
if(@ARGV == 2 && $ARGV[0] =~ /^(enable|disable)$/ && $ARGV[1] =~ /^(default|security|updates|proposed|backports)$/) {
    $action = $ARGV[0];
    $distribution = $ARGV[1];
}
else {
    printUsage;
}

parse;
rewrite;

exit(0);

相关内容