apt-show-versions 错误处理思路

apt-show-versions 错误处理思路

现象

执行 apt-get update 时出现
apt-show-versions 错误处理思路

出现

Use of uninitialized value $value in substitution (s///) at /usr/bin/apt-show-versions line 594, <FILE> line 348120.

使用print-debug大法

找到错误的文件

/usr/bin/apt-show-versions
复制一份到桌面或home文件中, 进行备份, 防止自己改错后无法恢复

找到错误区域

apt-show-versions 错误处理思路

因为本人之前根本没有接触 perl 的语法,所以只能通过百度、还有自己的猜测尝试理解上面的语句

熟悉编程的同学都知道 split 是一个常用的字符串分割函数
那么这个 split ,应该可能就是perl一个函数调用方式
逗号前后应该就是两个参数,函数返回一个元组
第一个参数看格式应该是一个正则表达式
所以下面语句的理解就是

($key, $value) = split /: /, $_;
# $_ 应该是一个临时变量,类型是字符串
# 将这个字符串分割成两个字符串,分别存入$key 和 $value中

再观察错误信息

Use of uninitialized value $value

也就是说在下面使用的时候 $value 这个变量是空的
那么做出猜测就是在进行字符串分割时出错。
那么接下来将这个字符串打印出来,看有什么特别之处
对代码进行修改

# 在前面加上 print
print $_;
($key, $value) = split /: /, $_;

再次执行apt-get update,查找错误
apt-show-versions 错误处理思路

我们发现在包 gtk-theme-imac中的信息有问题
其中version和其他包不太一样
其他包都在冒号后面有个空格
这个很有可能就是造成识别不了的罪魁祸首

验证猜测

我们将 $key 和 $value 分别打印出来查看
将刚才的那句print删除, 修改代码

($key, $value) = split /: /, $_;
print "Key: $key\n";
print "Value: $value\n";

找到错误位置
apt-show-versions 错误处理思路
很明显就是因为冒号后面没有空格
记得将加进去的两句print删掉

进行修正

分析代码
分析与错误代码有关联的代码片段

sub parse_file {
    my ($file, $status) = @_;
    my ($key, $value, $package, $packages);

    my $release = &determine_pkgfile_release($file);
    open FILE, $file or &die("Can't open file $file: $!\n");
    if ($opts{'verbose'}) {print "Parsing $file...";};
    while (<FILE>) {
        if (/^$/){
            unless (defined $package) {next};

            if ($status) { # Are we parsing the status file?
                # if we did not specify a package or pattern
                # only include installed packages
                unless ($mode == $MODE_ALL and
                        ($package->{$STATUS} =~ /not-installed|config-files/ or
                         # don't print holded packages if requested
                         ($opts{'nohold'} and $package->{$STATUS} =~ /hold/))) {
                    $packages->{$package->{$PACKAGE}}{$package->{$ARCH}} = $package;
                }
            }
            else {
                if (!defined $packages->{$package->{$PACKAGE}} or
		    !defined $packages->{$package->{$PACKAGE}}{$package->{$ARCH}}{$VERS} or
                    $vs->compare($packages->{$package->{$PACKAGE}}{$package->{$ARCH}}{$VERS},
			 $package->{$VERS}) < 0) {
                    $package->{$RELEASE} = $release;
                    $packages->{$package->{$PACKAGE}}{$package->{$ARCH}} = $package;
                }
            }
            undef $package;
            next;
        }
        unless ((/^Package/) || (/^Version/) || (/^Status/) || (/^Source/) || (/^Architecture/)) {next};
        ($key, $value) = split /: /, $_;
        $value =~ s/\n//;
        $value =~ s/\s\(.*\)$//; # Remove any Version information in ()
        $package->{$key} = $value;
    }
    if ($opts{'verbose'}) {print " completed.\n"};
    close FILE;
    return $packages, $release;
}

易得这个是类似函数一样的东西
那么分析函数就是以下步骤:

  1. 函数的意义
  2. 函数的输入输出参数
  3. 函数的返回值

先是函数的意义, 从函数名看起
parse_file 中文翻译 文件解析
那不用说了吧, 参数肯定有文件路径之类的

而且前面的那些打印出来的信息很有可能就是存在文件中
那么我们接下来就是找到这个文件, 对文件中的数据进行修正
其中 @_ 引起了我的注意, 我尝试把它打印出来

sub parse_file {
    # 打印 @_
    print "@_\n";
    my ($file, $status) = @_;
    my ($key, $value, $package, $packages);

    my $release = &determine_pkgfile_release($file);
    open FILE, $file or &die("Can't open file $file: $!\n");

现象
apt-show-versions 错误处理思路

/var/lib/apt/lists/packages.deepin.com_deepin_dists_panda_main_binary-amd64_Packages

当解析到这个文件时, 出现错误, 那么错误很有可能就在这个文件中

找到错误位置
apt-show-versions 错误处理思路
在冒号之后添加空格
修正后
apt-show-versions 错误处理思路

将那行print删除
执行 apt-get update
apt-show-versions 错误处理思路
修正成功!!!