apt-show-versions 错误处理思路
apt-show-versions 错误处理思路
现象
执行 apt-get update 时出现
出现
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文件中, 进行备份, 防止自己改错后无法恢复
找到错误区域
因为本人之前根本没有接触 perl 的语法,所以只能通过百度、还有自己的猜测尝试理解上面的语句
熟悉编程的同学都知道 split 是一个常用的字符串分割函数
那么这个 split ,
应该可能就是perl一个函数调用方式
逗号前后应该就是两个参数,函数返回一个元组
第一个参数看格式应该是一个正则表达式
所以下面语句的理解就是
($key, $value) = split /: /, $_;
# $_ 应该是一个临时变量,类型是字符串
# 将这个字符串分割成两个字符串,分别存入$key 和 $value中
再观察错误信息
Use of uninitialized value $value
也就是说在下面使用的时候 $value 这个变量是空的
那么做出猜测就是在进行字符串分割时出错。
那么接下来将这个字符串打印出来,看有什么特别之处
对代码进行修改
# 在前面加上 print
print $_;
($key, $value) = split /: /, $_;
再次执行apt-get update,查找错误
我们发现在包 gtk-theme-imac中的信息有问题
其中version和其他包不太一样
其他包都在冒号后面有个空格
这个很有可能就是造成识别不了的罪魁祸首
验证猜测
我们将 $key 和 $value 分别打印出来查看
将刚才的那句print删除, 修改代码
($key, $value) = split /: /, $_;
print "Key: $key\n";
print "Value: $value\n";
找到错误位置
很明显就是因为冒号后面没有空格
记得将加进去的两句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;
}
易得这个是类似函数一样的东西
那么分析函数就是以下步骤:
- 函数的意义
- 函数的输入输出参数
- 函数的返回值
先是函数的意义, 从函数名看起
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");
现象
/var/lib/apt/lists/packages.deepin.com_deepin_dists_panda_main_binary-amd64_Packages
当解析到这个文件时, 出现错误, 那么错误很有可能就在这个文件中
找到错误位置
在冒号之后添加空格
修正后
将那行print删除
执行 apt-get update
修正成功!!!