+ -
当前位置:首页 → 问答吧 → 【教学】自动重拨 PPPoE ADSL 连线 (For Linux & FreeBSD)

【教学】自动重拨 PPPoE ADSL 连线 (For Linux & FreeBSD)

时间:2004-10-17

来源:互联网

不管是 Linux 或是 BSD 下所使用的 PPPoE 拨号程式,在遇到很多奇怪的断线状况似乎并不能很自动的自己重拨,所以我写了这个 Script , 相信很多人都用的上.

引用:
星期六, 三月 19, 2005
FreeBSD 的 PPPoE ADSL 断线自动重拨

不管是 Linux 或是 BSD 下所使用的 PPPoE 拨号程式,在遇到很多奇怪的断线状况似乎并不能很自动的自己重拨,所以我写了这个 Script , 相信很多人都用的上.

因为后来新版的 Perl 对 system/exec 等指令的传回值处理方式似乎已经不同,最好的侦测方式是用 Perl Module,而不是呼叫系统指令,所以需要先装 Net::Ping::External

用 CPAN 来安装的话请依照以下步骤 ( CPAN 还没设定过的请先设定):

perl -MCPAN -e shell

cpan shell -- CPAN exploration and modules installation (v1.7601)
ReadLine support enabled

cpan> install Net::Ping::External

装好用就可以使用下面这个 script . 我使用的环境是 FreeBSD , 如果不是这个环境请自行修里面有用到的系统指令的路径,还有修改 $PPPoE_command 变数.

在跟 PC Zone 阿土站长 讨论过以后,我稍微改了一下程式并附上我自己的 ppp.conf
不使用 killall 来砍掉 ppp 的 pid 是顾虑到这个 command 在 Linux 可能没有,所以我采用比较传统的方式处理.

-------------------------------------------------------------
以下是我的 /etc/ppp.conf 内容 (参考 FreeBSD Handbook):


default:set log Phase tun command # you can add more detailed logging if you wishset ifaddr 10.0.0.1/0 10.0.0.2/0hinet:set device PPPoE:rl0set authname 你的帐号@hinet.netset authkey 你的密码set dialset loginadd default HISADDRnat enable yes
启动 PPPoE 的方式我是建议写在 /etc/rc.local ,加上一行:

/usr/sbin/ppp -ddial hinet

---------------------------------------------------------
以下为 Script 内容:
##############################################
#!/usr/local/bin/perl

$|=1;

#=============================================
# Programming by Dekuo Kuo in 2005/02/13
# http://www.dekuo.com/
#
# This script is running on FreeBSD.
# When you run it on other Unix like OS,
# modify below variable $PPPoE_command and
# system command path used in this script

$PPPoE_command = '/usr/sbin/ppp -ddial hinet';
#=============================================


if (ping_basic('168.95.1.1') != 1 && ping_basic('192.72.80.36') != 1) {
$pid_reference = get_pid("$PPPoE_command");
print "ADSL Link Down\n";

foreach $pid (@$pid_reference) {
print "Kill pid=$pid ...\n";
system("/bin/kill $pid") if $pid != '';
}

system("$PPPoE_command");
system("/bin/date >> /var/log/check_pppoe.log");
} else {
print "ADSL Link Up\n";
}

sub get_pid {
$process_string = $_[0];
$process_string = "\'" . $process_string . "\'";
@ps_data = grep {!/grep/} `ps -ax | grep $process_string`;

my @pid_list;
foreach (@ps_data) {
@ps_line = grep { $_ ne ''} split(/\s+/,$_);
push(@pid_list,$ps_line[0]);
}

return \@pid_list;
}

sub ping_basic {
use Net::Ping::External qw(ping);
my $device_ipv4 = $_[0];
my $alive = ping(hostname => "$device_ipv4", timeout => 5, count => 5, size => 1024);
return $alive;
}
##############################################

最后 ,当然不要忘了在 crontab 里加一行 ... 大概 5 分钟检查一次应该够了

crontab 范例 (当然要先建立 /root/script 这个目录) :
*/5 * * * * /root/script/check_pppoe.pl


如果您用的是 FreeBSD 5.x 的版本, 请在 crontab 最上面放下面这两行叙述:
SHELL=/bin/tcsh
PATH=/etc:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin

否则会让 perl 找不到相关 module

也就是说,如果您用的是 FreeBSD 5.x 以上的版本, 您的 crontab 内容就必须是这样:
SHELL=/bin/tcsh
PATH=/etc:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin
*/5 * * * * /root/script/check_pppoe.pl

为什么 FreeBSD 5.x 不能够使用 /etc/crontab 的 Shell 参数,这点我还不明白,如果有人瞭解的还请麻烦留言告知

另外, 如果有人在 Linux 环境下使用, 也请告诉我, 我想知道 Linux 下的 Command 路径有没有变

作者: dekuo   发布时间: 2004-10-17

这几天找了不少 PPPoE in FreeBSD 的资料 (ppp / mpd)
但很少看到有人讨论到断线重连部分
dekuo 的这篇教学刚好可以拿来研究一下 , Thanks!

作者: 阿 土   发布时间: 2004-10-17

引用:
最初由 阿 土 发表
这几天找了不少 PPPoE in FreeBSD 的资料 (ppp / mpd)
但很少看到有人讨论到断线重连部分
dekuo 的这篇教学刚好可以拿来研究一下 , Thanks!
我查过 ppp 的 Man page 说明, -ddial 应该就是会一直保持连线的参数,
但是我还是发现会有断线没自动重拨的现象 ... 所以不管我的 script 是否多此一举(或许有更正确的系统设定方式?) ,但是至少可以保证用了之后必定能够自动重拨 .... 但是 ATU-R 当掉的大概就没办法了 ..

作者: dekuo   发布时间: 2004-10-18

引用:
最初由 dekuo 发表
我查过 ppp 的 Man page 说明, -ddial 应该就是会一直保持连线的参数,
但是我还是发现会有断线没自动重拨的现象 ... 所以不管我的 script 是否多此一举(或许有更正确的系统设定方式?) ,但是至少可以保证用了之后必定能够自动重拨 .... 但是 ATU-R 当掉的大概就没办法了 ..
没错 , 这几天测试下来 ppp 当断线时有时并不会自动重拨
使用您这个 script 测几天看看

我用 ppp 拨接上 ftp.nsysu.edu.tw 抓几百 MB 的 ISO 档
随著抓取档案的速度越来越快 , ppp 的 cpu usage 也持续爬升
改用 mpd 拨接后 , cpu usage 比 ppp 少了许多
不过不知为何 , 有时会发生无法拨上线的状况 , 所以还是改回 ppp 拨接
因为以上传为主的 SERVER , 其 ppp 的 usage 并不会太高

作者: 阿 土   发布时间: 2004-10-18

引用:
最初由 阿 土 发表
没错 , 这几天测试下来 ppp 当断线时有时并不会自动重拨
使用您这个 script 测几天看看

我用 ppp 拨接上 ftp.nsysu.edu.tw 抓几百 MB 的 ISO 档
随著抓取档案的速度越来越快 , ppp 的 cpu usage 也持续爬升
改用 mpd 拨接后 , cpu usage 比 ppp 少了许多
不过不知为何 , 有时会发生无法拨上线的状况 , 所以还是改回 ppp 拨接
因为以上传为主的 SERVER , 其 ppp 的 usage 并不会太高
若是使用其它 PPP 拨号程式也可以用我吶 script ..

只要改掉这两行就行:

$pid = get_pid("/usr/sbin/ppp -ddial $PPPoE_profile");
这行是你程式用 ps 查到的字串,可以改成你在用的 mpd

system("/usr/sbin/ppp -ddial $PPPoE_profile");
这行是您要启动的 PPP 拨号程式指令

作者: dekuo   发布时间: 2004-10-18

又断线了 , 以 ps -aux | grep ppp 找到很多笔 ppp 的资料

引用:
root 61858 0.0 0.1 2704 1744 ?? Ss 12:32AM 0:00.10 /usr/sbin/ppp -d
root 61837 0.0 0.1 2704 1744 ?? Ss 12:31AM 0:00.11 /usr/sbin/ppp -d
root 61701 0.0 0.1 2704 1748 ?? Ss 12:27AM 0:00.17 /usr/sbin/ppp -d
root 530 0.0 0.1 2836 1836 ?? Ss 8:39AM 11:38.01 /usr/sbin/ppp -d
script 改成 "killall ppp" 直接把所有 ppp 停掉再做重拨是否会比较好?

作者: 阿 土   发布时间: 2004-10-19

引用:
最初由 阿 土 发表
又断线了 , 以 ps -aux | grep ppp 找到很多笔 ppp 的资料



script 改成 "killall ppp" 直接把所有 ppp 停掉再做重拨是否会比较好?
因为你执行 ppp 的指令跟我不同 ...所以要改成这样:

$pid = get_pid("/usr/sbin/ppp -d");

你会发现很多支 ppp 是因为没砍掉又重复执行 ...
只要把喂给 get_pid 的识别字串打对,应该都找的出来
用 killall 当然很棒 ...可是在 Linux 下好像就没这个指令了
所以我才用比较基础的方式来比对

我找时间在改一下 Script ,然后公布我自己用的 ppp.conf 好了 ...
这样大家比较看的懂我的 script 怎么用

作者: dekuo   发布时间: 2004-10-19

引用:
最初由 dekuo 发表
因为你执行 ppp 的指令跟我不同 ...所以要改成这样:

$pid = get_pid("/usr/sbin/ppp -d");
是我 key 错了 , 其实也是 "ppp -ddial hiet"

不过开机后的第一个 ppp process 却是 "/usr/sbin/ppp -quiet -ddial -nat hinet"

不过 ppp.conf 并没有设定 nat , 也不知道怎么会跑出来的

引用:
我的 ppp.conf

default:
set log phase tun command
enable dns

hinet:
set device PPPoE:fxp1
set mtu 1492
set mru 1454
set speed sync
enable lqr
set cd 5
set dial
set ctsrts off
set ifaddr 10.0.0.1/0 10.0.0.2/0
set login
add default HISADDR
set authname hinet-id
set authkey password
set timeout 0
set redial 3 5
set lqrperiod 5
set reconnect 5 10000
引用:
rc.conf 的设定

ppp_enable="YES"
ppp_mode="ddial"
ppp_profile="hinet"

作者: 阿 土   发布时间: 2004-10-19

引用:
最初由 阿 土 发表
是我 key 错了 , 其实也是 "ppp -ddial hiet"

不过开机后的第一个 ppp process 却是 "/usr/sbin/ppp -quiet -ddial -nat hinet"

不过 ppp.conf 并没有设定 nat , 也不知道怎么会跑出来的
你 config 档写太复杂了 ...看看我的 ..
我已经改过重新 Post 了

新版自动拨号 Script

如果您有启动 natd 也要关掉 ...用 ppp 的 NAT 就好了

作者: dekuo   发布时间: 2004-10-19

引用:
最初由 dou0228 发表
刚写了一个用 TCP 连 Port 80 的 PHP script

Ping 其实有的时候会被 ISP 无端的档下来..
用 Ping 用一定的风险在

TCP 连 HTTP 也不是没风险..
只是较不会像 ICMP 那样常被栏下来..

他会乱数的取 Server 列表去连网页
万一发现 连不上, 它会试三次, 不行才会重新启动 ppp

注: killall 在 Linux Distro. 里会有, 请放心
嗯嗯 ..您这程式写的更完善 ... 真是不错 ^_^

不过我不用 killall 的原因是其实我的 script 也可以用在其它 Unix ...例如 Solaris 就没有内建 killall 这个指令

而且我用 Perl 写的原因是因为 Perl 应该是所有 Unix Like OS 都会内建的程式,但是 PHP CLI 却得靠 User 自己另外做 (或者是 RedHat 完整安装也会做出 PHP CLI ? 但不见得每个 User 都会完整安装)

另外我相信 Hinet 也没那个狗胆去挡 ICMP ... 其它够种的 ISP 我就懒的管了

当然啦 ... 我的看法是用 Perl 来写出您那个程式的版本是最理想的啦 ... ^_^

作者: dekuo   发布时间: 2004-10-19

真是惭愧 ... 我之前手贱改过这支 script 就没再全程测试一遍 ...
今天才发现我自己的 bsd 断了但是 ppp 不但没砍掉还累积了一堆 ppp process ...

我有再度采用比较严谨的方式改写 script .. 这次确定可以用 ...
不过我猜要用在 Linux 可能得确认一下 ps 指令取得的结果 ... 否则我抓的 pid 栏位会不准 ...

等我想到比较好的方式再来修改好了 ..

2004/10/23 版 script

作者: dekuo   发布时间: 2004-10-23

引用:
最初由 dou0228 发表
ps 在 Linux/FreeBSD 命令还算有相关性, 如果到了 Solaris 可就( 没记错的话是 ps -ef )
我的建议是根本不要用 ps 去判断, 因为有 portable 问题

解法则是:
1. 不要用 Script 啦, 用 C 写, 以 EXEC(3) 那类的执行, 自然可以控制 pppd, 但是要小心使用 EXEC(3) 那类的函式, 否则会有安全性问题
2. 以 pppd 的 pidfile 来做不就得了, 这样解起来就容易的多

pppd 有一个选项: linkname <name>
因此, pppd 会建立 /var/run/ppp-<name>.pid 或是 /etc/ppp/ppp-<name>.pid
如此, 该档案内容自然就是 pid 囉
而且这样可以同时跑两个 pppd 也不须要 killall 砍掉其它的 pppd
ccc ... 我承认我的 script 现在只适合 FreeBSD Only ... 因为我真的没 Linux 的环境可以测试,也懒的测

我是认为这种东西用 C 写就太累了 .... 侦测 process 这种事情并没有啥 performance 方面的问题,至於 /var/run/xxx.pid 的机制也不是每种 Unix 都会乖乖的产生

所以我还是喜欢 perl or php 写出来的版本,比较好散布 ...
在处理 PID 的部份,的确有更精准的方式 ...但是 ... 目前来看应该够准了啦 ... 如果这是用於企业重要的 ADSL ... 自然还有很多方法可以写的超严谨

至於您提到的同时 Run 两个 ppp 的问题,我的确没考虑过 ...不过一般人应该比较少用到 ...

这是我的看法 ... 很高兴跟您讨论

可以 PM 我斯小讨论技巧,交换心得

作者: dekuo   发布时间: 2004-10-26

感谢阿...我一改完...
测速就快了10kbps左右...

是幻觉吗!?

作者: dshyi   发布时间: 2005-02-11

FreeBSD 的 PPPoE ADSL 断线自动重拨 2005/03/19 Update

作者: dekuo   发布时间: 2005-02-13

引用:
作者: dekuo
FreeBSD 的 PPPoE ADSL 断线自动重拨 2005/03/19 Update
又有新版程式 , 有新增哪些功能吗 ?
这支程式对於以 linux or FreeBSD 搭配 ADSL 架站的朋友来说 , 真的是超实用的
以下是我错误的 log 档 , 今天也有发挥几次作用 , 减缓当站的时间
引用:
Wed Dec 29 12:00:06 CST 2004
Wed Dec 29 12:05:06 CST 2004
Sat Jan 22 10:55:05 CST 2005
Sat Jan 22 11:00:05 CST 2005
Mon Feb 7 16:50:05 CST 2005
Mon Feb 7 16:55:05 CST 2005
Wed Mar 2 08:35:05 CST 2005
Wed Mar 2 08:40:06 CST 2005
Wed Mar 2 08:45:05 CST 2005
Wed Mar 2 08:55:06 CST 2005
Wed Mar 2 09:00:05 CST 2005
Fri Mar 11 18:15:05 CST 2005
Fri Mar 11 18:20:05 CST 2005
Thu Mar 24 22:55:06 CST 2005
Thu Mar 24 23:00:05 CST 2005
Thu Mar 31 17:10:05 CST 2005
Thu Mar 31 17:15:06 CST 2005
Thu Mar 31 17:20:05 CST 2005
Thu Mar 31 17:25:05 CST 2005

作者: 阿 土   发布时间: 2005-03-31

引用:
作者: ADMIN
又有新版程式 , 有新增哪些功能吗 ?
这支程式对於以 linux or FreeBSD 搭配 ADSL 架站的朋友来说 , 真的是超实用的
以下是我错误的 log 档 , 今天也有发挥几次作用 , 减缓当站的时间
我看您的 log 好像 5 分钟就断一次 .. 您应该没改成最新的版本 ...
这篇程式我改过三次, 第一版的会判断 PID 错误 ... 所以会每次执行每次误砍 ppp
第二版的程式才是改成可以正确执行的 ..
至於第三版, 程式没啥问题, 我是加了下面这段文字:
语法:
如果您用的是 FreeBSD 5.x 的版本, 请在 crontab 最上面放下面这两行叙述:
SHELL=/bin/tcsh
PATH=/etc:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin 否则会让 perl 找不到相关 module 也就是说,如果您用的是 FreeBSD 5.x 以上的版本, 您的 crontab 内容就必须是这样:
SHELL=/bin/tcsh
PATH=/etc:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin
*/5 * * * * /root/script/check_pppoe.pl 为什么 FreeBSD 5.x 不能够使用 /etc/crontab 的 Shell 参数,这点我还不明白,如果有人瞭解的还请麻烦留言告知 
详细的全文还是到 我 blog 上看比较准

作者: dekuo   发布时间: 2005-04-02

引用:
作者: dekuo
FreeBSD 的 PPPoE ADSL 断线自动重拨 2005/03/19 Update
((不好意思...档案已经找不到了))

之前我也有调整过相关的设定
但有时候我故意去把小乌龟的线拔掉来制造断线的状况(电话线端)
发现会侦测不出来

到最后我就直接改成每天固定在清晨的时候自动重拨一次(开始变懒了 )

作者: selfhu   发布时间: 2007-07-27

这script 真是太棒囉,又学到不少知识,先谢过各位囉.

作者: artsppdaniel   发布时间: 2009-01-20