2018年12月18日星期二

Linux启动时出现grub>提示符怎么办?

Grub是计算机启动的时候,加载操作系统的程序。出现grub>提示符说明grub程序找不到要加载的操作系统,这种情况最常见的原因是grub的配置文件丢失或损坏了。
现在的计算机一般都有专门用于启动的efi分区,grub也越来越复杂,说实话我还没有研究明白怎么恢复grub的配置文件。我写这篇文章的目的,是讲讲这种情况怎么在不重装系统的情况下进入Linux系统,并试图修复。
在grub提示符下,输入set命令,屏幕上会显示一堆堆的形如KEY=value的参数列表,往往一屏都显示不下,按空格键还有第二屏,需要从中找到一个kernelopts的参数,记下等号后面的参数(可能不止一行,下一行如果不是key=value的形式,那么仍然是当前行的继续)。
此时在grub命令提示符下输入
linuxefi /vmlinuz-xxxx kernelopts-value
如果grub提示找不到linuxefi这个命令,那就输入linux16命令, vmlinuz-后面的xxxx表示linux内核的版本号,此时输入Tab建,即可列出可选的内核;kernelopts就是刚才说的kernelopts对应的value, 一般来说只输入root=这个参数就可以了,其他参数可加可不加,都能进入Linux系统。
接下来在grub命令提示符下输入
initrdefi /initramfs-xxxx
xxxx也表示Linux内核同一版本号,通过Tab键补全即可。如果initrdefi找不到则使用initrd16命令。
最后在grub命令提示符下输入
boot
即可进入Linux系统。进入Linux系统后,通过rpm或者deb包的方式重新安装一下最新版本的内核,安装包脚本会自动配置grub的配置文件。一切正常的话,下次开机grub就配置好了可以正常使用了。

2018年12月4日星期二

不要在名为poll的函数中调用libcurl库,否则进程可能崩溃

最近写的一个程序中,通过调用libcurl库,实现对FTP服务器的上传下载功能。其中一个入口函数叫做poll的线程启动的时候,首先将之前积累的log文件通过libcurl上传到FTP服务器。结果运行的时候,进程直接就挂掉了。通过gdb分析core文件,发现崩溃前的栈如下:
Stack trace of thread 6127:
                #0  0x00007f41d8504e0d __GI___readdir64 (libc.so.6)
                #1  0x000000000040667e update_log_file (bas-ctl)
                #2  0x0000000000406894 poll (bas-ctl)
                #3  0x00007f41d86654c9 n/a (libcurl.so.4)
                #4  0x00007f41d865f030 curl_multi_wait (libcurl.so.4)
                #5  0x00007f41d8658433 curl_easy_perform (libcurl.so.4)
                #6  0x00000000004077c0 ftp_upload (bas-ctl)
                #7  0x000000000040670d update_log_file (bas-ctl)
                #8  0x0000000000406894 poll (bas-ctl)
                #9  0x00007f41d86654c9 n/a (libcurl.so.4)
                #10 0x00007f41d865f030 curl_multi_wait (libcurl.so.4)
                #11 0x00007f41d8658433 curl_easy_perform (libcurl.so.4)
                #12 0x00000000004077c0 ftp_upload (bas-ctl)
                #13 0x000000000040670d update_log_file (bas-ctl)
                #14 0x0000000000406894 poll (bas-ctl)
                #15 0x00007f41d86654c9 n/a (libcurl.so.4)
                #16 0x00007f41d865f030 curl_multi_wait (libcurl.so.4)
                #17 0x00007f41d8658433 curl_easy_perform (libcurl.so.4)
                #18 0x00000000004077c0 ftp_upload (bas-ctl)
                #19 0x000000000040670d update_log_file (bas-ctl)
                #20 0x0000000000406894 poll (bas-ctl)
                #21 0x00007f41d86654c9 n/a (libcurl.so.4)
                #22 0x00007f41d865f030 curl_multi_wait (libcurl.so.4)
                #23 0x00007f41d8658433 curl_easy_perform (libcurl.so.4)
                #24 0x00000000004077c0 ftp_upload (bas-ctl)
                #25 0x000000000040670d update_log_file (bas-ctl)
                #26 0x0000000000406894 poll (bas-ctl)
                #27 0x00007f41d86654c9 n/a (libcurl.so.4)
                #28 0x00007f41d865f030 curl_multi_wait (libcurl.so.4)
                #29 0x00007f41d8658433 curl_easy_perform (libcurl.so.4)
                #30 0x00000000004077c0 ftp_upload (bas-ctl)
                #31 0x000000000040670d update_log_file (bas-ctl)
                #32 0x0000000000406894 poll (bas-ctl)
                #33 0x00007f41d86654c9 n/a (libcurl.so.4)
                #34 0x00007f41d865f030 curl_multi_wait (libcurl.so.4)
                #35 0x00007f41d8658433 curl_easy_perform (libcurl.so.4)
                #36 0x00000000004077c0 ftp_upload (bas-ctl)
                #37 0x000000000040670d update_log_file (bas-ctl)
                #38 0x0000000000406894 poll (bas-ctl)
                #39 0x00007f41d86654c9 n/a (libcurl.so.4)
                #40 0x00007f41d865f030 curl_multi_wait (libcurl.so.4)
                #41 0x00007f41d8658433 curl_easy_perform (libcurl.so.4)
                #42 0x00000000004077c0 ftp_upload (bas-ctl)
                #43 0x000000000040670d update_log_file (bas-ctl)
                #44 0x0000000000406894 poll (bas-ctl)
                #45 0x00007f41d86654c9 n/a (libcurl.so.4)
                #46 0x00007f41d865f030 curl_multi_wait (libcurl.so.4)
                #47 0x00007f41d8658433 curl_easy_perform (libcurl.so.4)
                #48 0x00000000004077c0 ftp_upload (bas-ctl)
                #49 0x000000000040670d update_log_file (bas-ctl)
                #50 0x0000000000406894 poll (bas-ctl)
                #51 0x00007f41d86654c9 n/a (libcurl.so.4)
                #52 0x00007f41d865f030 curl_multi_wait (libcurl.so.4)
                #53 0x00007f41d8658433 curl_easy_perform (libcurl.so.4)
                #54 0x00000000004077c0 ftp_upload (bas-ctl)
                #55 0x000000000040670d update_log_file (bas-ctl)
                #56 0x0000000000406894 poll (bas-ctl)
                #57 0x00007f41d86654c9 n/a (libcurl.so.4)
                #58 0x00007f41d865f030 curl_multi_wait (libcurl.so.4)
                #59 0x00007f41d8658433 curl_easy_perform (libcurl.so.4)
                #60 0x00000000004077c0 ftp_upload (bas-ctl)
                #61 0x000000000040670d update_log_file (bas-ctl)
                #62 0x0000000000406894 poll (bas-ctl)
                #63 0x00007f41d86654c9 n/a (libcurl.so.4)

其中bas-ctl中的这几个函数是我写的,看起来发生了循环调用。我在ftp_upload函数中调用了libcurl的函数后,libcurl.so.4中的一个不知名的函数会重新调用我的线程入口poll函数。如此往复循环,直接把栈给干爆了。这种情况我还是第一次遇到。
考虑到我的程序是多线程的,在网上搜了一下多线程使用libcurl要注意的事项,发现大家说的都是那两点(可以网上自己搜,我在这里不赘述). 我把这些注意点在我的程序中改进后,仍然没有解决问题。
后来想libcurl.so.4为什么会重新调用我的poll函数?是不是libcurl中有相同的函数名?于是把poll改为bg_worker, 结果问题解决,函数名也更加见名知意了。

2018年11月28日星期三

2017年12月31日唐山所见(5)



开滦马家沟矿正门。我小时候每到节日,门口就会安装类似“欢度国庆”的霓虹灯,我妈就会带我去看。当时他们的职工小区领先其他小区通了瓦斯气用于做饭。后来,地下的煤采空了,这座矿也就废弃了,职工愿意的话,可以举家搬到外地继续开采煤炭。
每座煤矿都有这样一座井架,上面有两个大轮子昼夜不停地旋转。煤采空了,当然轮子也就不转了。

马矿门口附近的一条小路,对这条路我其实不怎么熟悉。

小时候去过的商店,早已废弃。窗户用砖头都堵上了。

曾经的唐钢医院,现在被民营资本买下来经营并改了名字。我小时候经常来这里看病。爸爸也是从这里去的天堂。

2018年11月27日星期二

Gnome网络参数设置对话框打不开的变通办法

点击Gnome桌面右上角的图标,可以对网络参数,如IP地址、DNS、Proxy等进行设置。然而我的PC不知道被我动了什么,这个对话框打不开了。
除了正面解决这个问题,修复损坏的组件或者配置文件外,还有其他变通的方式对这些参数进行设置。
1. IP地址和DNS服务器地址
安装NetworkManager-tui这个软件包。然后以管理员身份在命令行运行nmtui程序,会弹出一个基于文本的图形界面,通过键盘的上下左右键和Tab、回车键可进行操作。通过它可以设置IP地址、网关、DNS方面的设置。
2. Proxy
直接在命令行运行下面的命令,注意体换掉命令中的代理服务器地址和端口,其他类型的代理服务器以此类推
gsettings set org.gnome.system.proxy mode 'manual'
gsettings set org.gnome.system.proxy.http enabled true
gsettings set org.gnome.system.proxy.http host 'proxy.server.addr'
gsettings set org.gnome.system.proxy.http port proxy_port
如果服务器需要鉴权的话,增加下面的语句
gsettings set org.gnome.system.proxy.http authentication-user 'user_id'
gsettings set org.gnome.system.proxy.http authentication-password 'password'
如果所有类型的协议都是用相同的服务器地址和端口,增加下面的语句
gsettings set org.gnome.system.proxy use-same-proxy true
如果某些地址不使用代理,则增加下面的语句。例子中的地址是我这台电脑的设置,需要根据自己的需求进行替换
gsettings set org.gnome.system.proxy ignore-hosts "['*.csdn.net', '*.org', '*.alicdn.com', '*.tmall.com', '*.taobao.com', '*.yinxiang.com', '*.live.com', '*.163.com', '*.licdn.com', '*.linkedin.com', 'localhost', '127.0.0.0/8', '10.0.0.0/8', '::1', '*.huawei*.com', '*.qq.com', '*.263.net', '*.cn', '*.cupdata.com']"