免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 843 | 回复: 0
打印 上一主题 下一主题

架設 NEWS [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-09-09 11:51 |只看该作者 |倒序浏览

常上新聞組的朋友一定在那裡學到不少東西吧﹖您又有否想過自己架一個 NEWS 伺服器呢﹖﹖其實在有些企業內部﹐也會透過 NEWS 伺服器進行公告﹑技術討論﹑工作彙報等事情。好消息是﹕要架設一個 NEWS 伺服器並不難﹐下面的步驟就是教您如何在本地網路中架一個 NEWS 伺服器。
設定news
如果您當初在安裝的時候選擇 everything 的話﹐相信您的機器上面已經有一個叫“inn”的 NEWS 伺服器了。請打﹕ setup --> System services --> [ * ] innd ﹐就可以讓 innd 在每次啟動的時候載入了。不過﹐如果還沒啟動的話﹐也可以使用 /etc/rc.d/init.d/innd start 來將之啟動啦。
如果您的 innd 已經成功啟動﹐在預設的情況下﹐您已經有‘control’﹑‘control.cancel’﹑‘junk’﹑‘test’者四個新聞群組了。只要您用 NEWS 客戶程式(如 outlook 等)﹐連上您的 NEWS 伺服器﹐就可以看到上面的群組了。
小心哦﹕上述的四個群組不能刪除哦﹐否則您的 innd 可能跑不起來。如果您不想用戶連接到它們﹐那麼參考後面的說明修改/etc/news/nnrp.access這個設定檔。例如﹕
192.168.0.*:Read Post:::*,!control,!control.cancel,!junk,!test,!to
(這裡我要特別多謝 Startac 兄 提供的意見﹗)
如果您要增加新的群組﹐只要輸入﹕
ctlinnd newgroup test.netman 就可以增加一個叫‘test.netman’的新聞組了。您再用您的客戶程式重新連接就可以看得到。
如果您輸入﹕
ctlinnd rmgroup test.netman 就會剛才建立的群組移除掉。
這樣看來﹐要建立起一個 NEWS 伺服器似乎一點也不難。不過﹐有幾個檔案我們還是要修改一下的﹕
/etc/news/inn.conf
organization: netman's news site
這是用來設定組織名稱的﹐您看一看原來的句子可能會有會心的微笑。
server:                 redhat52.siyongc.domain
指定 NEWS 伺服器的名稱。
pathhost:               redhat52.siyongc.domain
指定群組的 path 。
moderatormailer:        webmaster@siyongc.domain
指定管制群組的管理者信箱。
domain:                 siyongc.domain
指定網域名稱。
fromhost:               redhat52.siyongc.domain
指定文章的‘From’地址。
其它的設定﹐使用預設則可。
/etc/news/expire.ctl
/remember/:14
只記錄兩星期的文章標題。
*:A:1:10:never
在預設情況下﹐所有文章都會保留‘1 至 10’天﹔而允許標題‘永不過期(never)’。不過﹐您也可以指定某些群組的保留期限﹐如﹕
netman.*:M:1:35:90
test.*:A:never:never:never
這樣﹐以‘netman.’開頭的群組都會最多保留 90 天。而以‘test.’開頭的群組則永遠保留。
/etc/news/nnrp.access
*.siyongc.domain:Read Post:::*
192.168.0.*:Read Post:::*
這樣﹐所有從‘siyongc.domain’或‘192.168.0’這個網域連上來的使用者都可以‘讀’和‘刊登’文章。
在修改上面的檔案時﹐請注意在句子後面不能有空白鍵﹐如果您不知道有否﹐執行
inncheck -v 就可以得知。使用這個命令﹐我們還可以得知要設定 NEWS 伺服器要修改的檔案有哪些﹐以及它們有沒有設定錯誤。
和其他news伺服器連接
NEWS 系統有一個功能是﹕新聞群組可以從一個伺服器傳給另外一個伺服器﹐一直傳遞開去﹐從而達到一信傳千里的效果。要做到這個目的﹐您得在各伺服器之間建立餵信(newsfeed)功能。這需要雙方伺服器的極度配合方可達成。
有些朋友喜歡用上游﹑下游來稱呼參與餵信過程的雙方﹐不過您也可以稱之為餵方(feeder)和受方(receiver)。因為 news 並非如 DNS 那樣的樹狀層級架構。比如 server A 和 server B 互有信件對傳﹐那麼它們之間既是上游﹐也是下游﹐端看信件的傳遞方向而定。
前面我們已經知道架設好 innd 之後﹐可以用 ctlinnd newgroup 來增加群組。但技術上來說﹐它只是增加一個 active 群組﹐您可以在 /var/lib/news/active 檔案裡面找到。不過﹐請您不要胡亂修改它﹐否則您可能失掉整個群組。但如果您要為該群組做些說明﹐可以修改 /var/lib/news/newsgroups 這個檔﹐將 active 裡面的群組名稱寫進去﹐然後在它後面增加一些說明。例如﹕我先用下面命令建立三個群組﹕
ctlinnd newgroup netman.test
ctlinnd newgroup siyongc
ctlinnd newgroup private

然後修改 /var/lib/news/newsgroup :
netman.test        A test group for netman
siyongc                A public group for siyongc
private                A private group
上面是手工的方法﹐如果您的上游 news server 有許多已經建立起來的群組﹐您想您的 server 也能接收(或回送)它們的文章﹐您必須要先將群組建立起來﹐這恐怕是一件非常累人的事情。不過﹐下面教您一個方法﹐一次過將上游的群組名單全部抓回來。
在我們這例子中﹐假設上游 server 叫做 news1.siyongc.domain ﹐而下游 server 叫 news2.home.siyongc.domain 。這個 news1 已經跑起來好一段日子了﹐且也接受外部的餵信﹐這個我們暫時不管它。而 news2 則是剛建立好﹐且測試過可以勝任本地新聞的工作。那麼我們在 news2 的主機上依順序輸入﹕
service innd stop
chown news:news /var/lib/news/*
su - news
telnet news1.siyongc.domain nntp > /tmp/active.new
list active
quit
telnet news1.siyongc.domain nntp > /tmp/newsgroups.new
list newsgroups
quit

您在 telnet 過程中熒幕是沒有顯示回應結果的﹐如果您想確定一下看到什麼﹐那就只輸入 " > " 之前的句子看看吧。然後您要修改新下載回來的 active.new 和 newsgroups.new 兩個檔﹐把開頭的 5 或 6 行(至那個以 215 開頭的句子)和最後 2 行文字刪除掉﹐這樣您就擁有和上游一模一樣的群組名單了。但這還不夠完整﹐您還要執行下面命令﹐重設 active 和 newsgroups 檔案﹕
(繼續保持 news 身份﹐否則 su -news)
cd /var/lib/news
cp active active.bak
cp newsgroups newsgroups.bak
awk '{ $2 = "0000000000" ; $3 = "0000000001" ; print }' /tmp/active.new >> active
cat active | sort -o active
cat /tmp/newsgroups.new >> newsgroups
cat newsgroups | sort -o newsgroups

您可能需要手工的修改上面檔案﹐將您原來的群組和新群組重複的部份刪除掉。最後執行 inncheck -v 看看是否有地方需要修改﹐有則根據提示改之﹐直到再沒錯誤才繼續。否則﹐您的 NEWS 可能跑不起來哦﹐盡管執行 service innd start 後您會看到 OK﹐您用 service innd status 就可以確定了。切記切記﹗
好了﹐當群組名單建立起來之後﹐我們就可以正式修改 innd 的檔案﹐以接受餵方的信件了。除非真有必要﹐我建議您保留 news 的身份來設定所有的 innd 檔案。不過好消息是﹕受方只需設定一個檔案就可以了﹐您只需修改 /etc/news/incoming.conf 檔﹐給餵方起一個名稱(可隨意)﹐然後將它的地址寫好就行﹕
peer news1 {
  hostname:        news1.siyongc.domain
}
設定完之後﹐可以用 root 身份重新 stop 和 start 那個 innd 服務以確定設定生效。但這動作可能不是必須的﹐如果不影響正常運作﹐做一下也無妨就是了。
雖然您把受方的大門打開了﹐如果餵方沒有相應的設定﹐那麼您還是收不到任何信件的。接下來﹐就是餵方的設定啦。這裡﹐我假設您已搖身一變成為餵方 server 的管理員了。 :)
在一切正常的情形下﹐餵方只需修改兩個檔案﹕ /etc/news/nntpsend.ctl 和 /etc/news/newsfeeds 。讓我們逐個來吧。一如設定受方的 incoming.conf 那樣﹐您必須為受方定義一個名稱(可隨意)﹐然後將地址寫到 nntpsend.ctl 檔案裡面﹕
news2:news2.home.siyongc.domain::
就這麼簡單﹐一行而已﹐如果您還要其它設定﹐可以 man nntpsend.ctl 。不過﹐請記著第一個 ":" 號前的名字﹐在下面的 newsfeeds 檔案裡面要使用和它一樣的名稱﹕
news2\
        :netman.*,siyong,!private,!junk,!control/!foo\
        :Tf,Wnm:
好了﹐這個檔案有必要解釋一下了。
  • 首先定義一個受方名稱﹐它和 nntpsend.ctl 裡面定義的要一致。
  • 然後在第一個 ":" 和第二個 ":" 之間﹐指定有哪些群組要餵送﹐各群組名稱用 "﹐" 來分隔。如果群組前面用 "﹗" 就表示該群組絕對不進行餵送。
  • 再來在第二個 ":" 和第三個 ":" 之間﹐指定了用哪些方式進行餵送。這裡設定是用 batch file 的方式﹐經由 innxmit 程式用 nntp 協定進行餵送。具體餵送方式的設定可以 man newsfeeds ﹐或參考
    http://bbs.ee.ntu.edu.tw/boards/NetNews/7/4/index.html

  • 如果還要其它設定﹐請自己參考資料﹐或 man newsfeeds 。
    當一切設定妥當之後﹐在 news1 的相關群組發表一些文章﹐看看 /var/spool/news/outgoing 目錄下面是否有 news2 這個 batch file 檔案。如果沒有﹐就試試重新啟動 innd ﹕
    su -
    service innd stop
    service innd start
    (不建議用 restart)
    service innd status (確定啟動正常)
    exit (回到 news 身份)
    如果 news2 檔案存在﹐可以 cat 一下看看是否有文章標號和 message-ID 出現。如果沒有可能要等一下﹐如果一直都沒有﹐那就可能是設定上某部份出現問題了(這個我就不是很確定了)。當萬事俱備之後﹐我們就可以進行餵送了﹕
    nntpsend
    然後看看 /var/log/news/nntpsend.log 有沒有錯誤信息。如果遇到什麼 "Ignoreing line ......" 的話﹐那可能是 batch file 的格式不對。如果用 innxmit 的話﹐請 man innxmit 看看格式規定是否和檔案一致。如果用其它的﹐請自行找資料。這就這要求您小心設定 newsfeeds 檔案了。
    假如 log 信息沒錯誤﹐那麼我相信受方那邊已經成功收到更新文章了。如果沒有的話﹐那重新檢查所有步驟吧﹐或到各 BBS 找答案吧。不過﹐當 batchfile 建立起來之後﹐您可以可以手工的用 innxmit 來試試看﹕
    innxmit -a -d news2.home.siyongc.domain news2
    小心哦﹐這樣可能會把 batch file 移除掉哦﹐不過您可以重新啟動 innd 建立回來啦。
    如果一切順利﹐那就開香賓慶祝一下吧﹗然後﹐您或許會希望 news2 回應的文章﹐也可以送回到 news1 去吧﹖現在相信難不到您啦﹐參考上面的設定﹐稍微改改餵方和受方名稱﹐然後換一台機器設而已啦。
    剛才我們是用 nntpsend 這個程式手工進行餵送的﹐如果您沒時間親自執行這個動作﹐最簡單莫過於用 crontable 來做啦。只要用 root 身份執行 crontable -u news -e﹐然後加入﹕
    0,10,20,30,40,50 * * * * /usr/bin/nntpsend
    醬子就大功告成啦 ~~~ 哇~﹗好開心哦~~~﹗﹗ ^_^
    設定 suck
    好了﹐前面說的餵信方式﹐要經過雙方伺服器的配合才能完成﹐那麼有沒有法子不需要上游餵進來﹐而主動去抓文章的辦法呢﹖當然有啦﹗用 suck 就可以做到﹐下面就和大家談談如何用 suck 抓信吧﹐而且還能 post 回去哦~~~
    這裡我要特別感謝 lman 兄的大力幫助﹐才讓我的測試順利完成。有興趣討論 suck 相關技術的朋友也可以找他研究一下的。
    當然﹐首先要做的事情是取得 suck 這隻程式﹐我這裡使用的是 suck-4.2.3-1.i386.rpm ﹐從
    http://rpmfind.net/linux/RPM/
    那裡抓的。直接用 rpm 安裝就好了﹐根本不用設定一大堆有的沒的﹐如 prefix 之類的東東。
    不過﹐在真正動手設定 suck 之前﹐我們首先要修改 innd ﹐以符合這個特殊的環境。首先﹐您不能像前面教的被動餵信模式那樣保留長長的一列 /var/lib/news/active 記錄。因為 suck 會依據 /var/lib/suck/sucknewsrc 這個檔案來決定到上游抓信。這本來沒什麼問題﹐您可以手工的修改它(請參考 man suck)﹐但在我目前使用的這個 rpm 套件版本﹐sucknewsrc 卻會在執行 get.news.inn (後面就會談到) 之後把群組名稱同步為 active 記錄裡面的名稱(假如您使用預設的 -A 選項)。如果您的 active 是滿滿的一大串﹐那麼下次執行 get.news.inn 的時候﹐恐怕會嘗試抓所有的群組信件回來﹐這樣子﹐就算您不計較時間和頻寬﹐您也得每天至少準備 500MB 的空間(取決於名單長度)來裝那些信件。(tips:您也可以修改 /var/lib/suck/active-ignore 檔案來指定哪些群組不用去抓。)
    這不同正常的被動模式那樣﹕可以通過 newsfeeds 和 incoming.conf 來限制群組名單哦﹐所以一定要小心設計 active﹐把不必要的群組拿掉。您可以手工刪除﹐也可以動一下腦筋去修改啦﹐比方我只想留 tw.bbs.comp 和本地的群組﹐我會這樣做﹕
    cd /var/lib/news
    cat active | grep "tw.bbs.comp" | awk '{ $2 = "0000000000" ; \
      $3 = "0000000001" ; print }' > active.tmp    # 同時完成歸零的動作
    cat active.bak > active    # 這是上次抓上游 active 時﹐原來的本機群組備份)
    cat active.tmp >> active

    不過﹐如果您不想 suck 全部把 active 的東都更新至 sucknewsrc 去﹐您可以在 /var/lib/suck 目錄下建立一個 active-ignore 檔﹐把一些本機的群組﹐或那些不想到上游抓的群組名單﹐一行一個的寫進裡面去。
    另外﹐您還得修改 /etc/news/newsfeeds ﹐為上游定義一個名稱﹐以及把您要回餵的群組寫進去。您可以
    參考前面
    所教的範例﹐不過﹐我現在的例子要用 news1 這個名稱哦﹗而且每次修改好 innd﹐別忘了讓 innd 重新讀入更新檔案或重新啟動。
    等安裝好 suck 之後﹐就進入 /var/lib/suck 這個目錄工作了。您全部要做的只是編輯一個檔案﹐修改 get.news.inn ﹐主要是下面這幾句就夠了﹕
    把您要抓的上游主機寫好﹕
    REMOTE_HOST=news1.siyongc.domain
    接著也給上游起一個名字﹐是用來把信件餵回上去的。要注意﹕這個名稱跟 newsfeeds 裡面所定義的要一至哦﹗
    SITE=news1
    如果您執行這個 script 沒問題的話﹐應該不用做什麼修改了。但如果您碰到“GROUP command not recognized, try the -M option”這樣的錯誤信息﹐那您還要修改另外兩行﹐在句子中插入一個 " -M " 選項﹕
    ......
        # download messages
        ${SUCK} ${REMOTE_HOST} -M -c -A -bp -hl ${LOCAL_HOST} -dt ${TMPDIR} -dm ${MSGDI
    R} -dd ${BASEDIR} -HF ${HISTORY}
    ......
                # outgoing messages to post
                ${RPOST} ${REMOTE_HOST} -M -d -b ${OUTGOINGNEW} -p ${SPOOLDIR} -f \$
    \$o=${OUTFILE} ${SCRIPT} \$\$i ${OUTFILE}
    ......
    這裡﹐我將修改過的的 get.news.inn 這個 script 內容列出來﹐希望對您有所參考。因為﹐在測試過程中曾對它修改了好多次﹐最後才變成目前這個樣子 (它是用來抓 hinet 上面的 news 用的)﹕
    #!/bin/sh
    #BEFORE USING - check to ensure all the paths defined below are correct!!
    #NOTE: this script probably needs to be run by root.  Most systems will
    # not let a normal user run ctlinnd
    REMOTE_HOST=news.hinet.net
    INN_DIR=/etc/news
    INN_CONF=${INN_DIR}/inn.conf
    LOCAL_HOST=localhost
    LOCAL_TEST=$(cat ${INN_CONF} | grep fromhost | awk '{print $2}')
    if [ "$LOCAL_TEST" != "" ]; then
            echo "Set LOCAL_INN to '$LOCAL_TEST'"
            LOCAL_INN=${LOCAL_TEST}
    fi
    SPOOLDIR=/var/spool/news/articles                # base directory for articles to be rposted
    NEWSDIR=/usr                                # base directory for news binaries
    BASEDIR=/var/lib/suck                        # base directory for scripts and data files
    FILTER=${BASEDIR}/newsfil.pl
    CTLINND=${NEWSDIR}/bin/ctlinnd                # location of binary
    SHLOCK=${NEWSDIR}/bin/shlock                # location of binary
    TMPDIR=${BASEDIR}                                # location for suck.* files
    MSGDIR=${BASEDIR}/Msgs                        # where to put MultiFile messages when getting them
    SITE=hinet                                # name of site from newsfeeds file
    OUTGOING=/var/spool/news/outgoing/${SITE}        # location of the list of articles to upload
    OUTGOINGNEW=${OUTGOING}.new                        # file to contain the list temporarily
    OUTGOINGFAIL=${OUTGOINGNEW}.fail                # file with failed xfers
    SCRIPT=${BASEDIR}/put.news                        # my filter for rpost
    OUTFILE=/tmp/tmp$$                                # used by rpost as article after it is filtered
    LOCKFILE=${BASEDIR}/getnews.lock                # lock file to prevent multiple instances of script
    NEWSGROUP=news                                # which group owns the file in out.going,
                                            # typically either news or uucp.
    TESTHOST=testhost
    RPOST=rpost
    SUCK=suck
    HISTORY=/var/lib/news/history                # location of history file
    # if we are already running, abort
    trap 'rm -f ${LOCKFILE} ; echo "Aborting" ; exit 1' 1 2 3 15
    ${SHLOCK} -p $$ -f ${LOCKFILE}
    if [ $? -ne 0 ]; then
            echo "Already running, can't run two at one time"
            exit
    fi
    # is the local host up and running so we can post messages we download?
    ${TESTHOST} ${LOCAL_HOST} -s
    LOCAL_RESULT=$?
    # is the remote host up and running so we can download messages?
    ${TESTHOST} ${REMOTE_HOST} -s
    REMOTE_RESULT=$?
    if [ ${REMOTE_RESULT} -eq 0 -a ${LOCAL_RESULT} -eq 0 ]; then
           
      # download messages
      if [ -x ${FILTER} ]; then
            ${SUCK} ${REMOTE_HOST} -c -A -bp -hl ${LOCAL_HOST} -dt ${TMPDIR}\
               -dm ${MSGDIR} -dd ${BASEDIR} -HF ${HISTORY} -y ${FILTER}
      else
            ${SUCK} ${REMOTE_HOST} -c -A -bp -hl ${LOCAL_HOST} -dt ${TMPDIR}\
               -dm ${MSGDIR} -dd ${BASEDIR} -HF ${HISTORY}
      fi
      SUCK_STATUS=$?
      if [ ${SUCK_STATUS} -eq 0 ]; then
            echo "Downloaded Articles"
      elif [ ${SUCK_STATUS} -eq 1 ]; then
            echo "No articles to download"
      elif [ ${SUCK_STATUS} -eq 2 ]; then
            echo "Unexpected answer from remote server to an issued command"
      elif [ ${SUCK_STATUS} -eq 4 ]; then
            echo "Can't do NNTP authorization"
      elif [ ${SUCK_STATUS} -eq -1 ]; then
            echo "General failure"
      fi
      # now upload messages
      # filtering outgoing articles
      if [ -s ${OUTGOING} ]; then
            echo "LOCAL_INN is ${LOCAL_INN}"
             echo "OUTGOING is ${OUTGOING}"
            echo "Filtering ${OUTGOING} ..."
            cat ${OUTGOING} | grep ${LOCAL_INN} > ${OUTGOING}
      fi
      if [ -s ${OUTGOINGNEW} ]; then
            echo "OUTGOINGNEW is ${OUTGOINGNEW}"
            echo "Filtering ${OUTGOINGNEW} ..."
            cat ${OUTGOINGNEW} | grep ${LOCAL_INN} > ${OUTGOINGNEW}
      fi
      if [ -s ${OUTGOING}  -o -s ${OUTGOINGNEW} ]; then
            ${TESTHOST} ${REMOTE_HOST} -s
              if [ $? -ne 0 ]; then
                    echo "Remote posting host not responding"
             else
                    # this is needed by INND so that the outgoing file will be
                    # properly flushed and we have a new blank file to work with
                    # when we are done
                    # First mv the current one to a new file name
                    # Since innd already has the file open, it doesn't care
                    # about the rename.
                    # The flush will ensure that all messages to be posted have
                    # been written out, close off the old one (already renamed)
                    # and create a new one.
                    # if the outgoingnew already exists, it means we aborted last time
                    # so don't try to do it again
                    if [ ! -s ${OUTGOINGNEW} ]; then
                      mv ${OUTGOING} ${OUTGOINGNEW}
                      ${CTLINND} flush ${SITE}
                    fi
                    # outgoing messages to post
                    echo "Posting outgoing articles..."
                    ${RPOST} ${REMOTE_HOST} -d -b ${OUTGOINGNEW}\
                       -p ${SPOOLDIR} -f \$\$o=${OUTFILE} ${SCRIPT} \$\$i ${OUTFILE}
                    ERRLEV=$?
                    if [ ${ERRLEV} -eq 0 ]; then
                      echo "Remotely posted articles"
                      rm ${OUTFILE}
                      elif [ ${ERRLEV} -eq 1 ]; then
                      echo "Error posting a message"
                    elif [ ${ERRLEV} -eq 2 ]; then
                      echo "Unable to do NNTP authorization with remote server"
                    elif [ ${ERRLEV} -eq 3 ]; then
                      echo "Unexpected answer from remote server to a command while doing NNTP authorization"
                    elif [ ${ERRLEV} -eq -1 ]; then
                      echo "Fatal error"
                    fi
                    if [ -f ${OUTGOINGFAIL} ]; then
                      mv ${OUTGOINGFAIL} ${OUTGOINGNEW}        # so we can re do it
                      chown news.${NEWSGROUP} ${OUTGOINGNEW}
                      chmod 664 ${OUTGOINGNEW}
                    fi
            fi
      fi       
           
      echo "Suck has finished the job, enjoy it!"
    fi
    rm -f ${LOCKFILE}
    ### added for restarting innd
    ### to make sure innd is running well.
    echo "Trying to restart innd..."
    sleep 5
    /etc/rc.d/init.d/innd stop
    sleep 10
    /etc/rc.d/init.d/innd start
    innstatus=`/etc/rc.d/init.d/innd status`
    chkinn=`echo ${innstatus} | grep 'pid'`
    if [ -z "$chkinn" ]; then
            echo "WARNING: something wrong with innd! Please fix it."
    else
            echo "$innstatus"
    fi
    exit 0
    不過﹐就算您的設定完全沒問題﹐根據我這裡的經驗﹐您還不能抓上游的文章啦。您必須還要幫 sucknewsrc 做一個歸零的動作﹕
    cat sucknewsrc | awk '{ $2 = "1" ; print }' > sucknewsrc
    然後再重新執行 get.news.inn 。
    假如您有時間﹐應該 man suck 看看如何設定這個 sucknewsrc 的﹐這樣您就可以對群組有更大的控制空間了。
    關於過濾
    雖然您能夠成功抓上游的文章了﹐但通常來說﹐您是沒選擇的。也就是上面有什麼您就抓什麼﹐不管好的﹑壞的﹑想要的﹑不想要的﹐都通通會抓下來。這不僅讓您在閱讀標題時非常“不爽”﹐而且還會浪費許多磁碟空間。
    這時候﹐您或許想用一些方法把那些不想要的文章過濾掉吧。剛好﹐最近在一位高手 AcE 兄的大力協助之下﹐寫了一個 script ﹐專門用來砍 news 文章用的。下面就和大家分享一下 ﹕
    #!/usr/bin/perl -P
    #
    #~~~~~~~~~~~
    #
    #        Purpose:        Filtering BAD news articles.
    #         Author:        netman
    #        Origin:        AcE
    #
    #        Version:        1.0.1
    #        Date:        2000/10/31
    #
    #        License:        GNU/GPL
    #
    #~~~~~~~~~~~
    if ( $ARGV[0] =~ /^$/) {
            printf "ERROR:  missing argument.\n";
            printf "        Syntax: $0 DIR_PATH\n\n";
            exit 1;
    }
    else {
            opendir (FDIR, $ARGV[0]) or die "ERROR: Can't open $ARGV[0].\n\n";
            close FDIR;
    }
    printf "Feltering BAD articles under $ARGV[0] ...\n";
    # List for Content filtering
    $CList="/var/lib/suck/clist";
    # List for 'Subject' filtering
    $SList="/var/lib/suck/slist";
    # List for 'From' filtering
    $FList="/var/lib/suck/flist";
    # List for 'Host' filtering
    $HList="/var/lib/suck/hlist";
    ########## Starting Content feltering:
    open(cList,"${CList}") or die "Can't open ${CList}.\n";
    $index=0;
    while()
    {
      chop;
      $keys[$index]=$_;
      #printf "$keys[$index]\n";
      $index++;
    }
    close(cList);
    for($i=0;$i wait4kill-c");
      open(killList,"./wait4kill-c");
      while(){
        if($_ =~ /^([^:]+):.*$/){
                    if($tt ne $1){
                   printf "Deleting $1 ...\n";
                       system("rm -f $1");
                       $tt=$1;
                    }
         }
      }
      close(killList);
    }
    system("rm -f ./wait4kill-c");
    ########## Starting 'Newsgroups' feltering:
    printf "Filtering Newsgroups...\n";
    system("grep -r '^Newsgroups.*tw.*tw.*.tw' $ARGV[0] > wait4kill-n");
    open(killList,"./wait4kill-n");
            while(){
         if($_ =~ /^(.+):Newsgroups.*$/){
           printf "Deleting $1 ...\n";
               system("rm -f $1");
         }
            }
    close(killList);
    system("rm -f ./wait4kill-n");
    ########## Starting 'Subject' feltering:
    open(sList,"${SList}") or die "Can't open ${SList}.\n";
    $index=0;
    while()
    {
      chop;
      $keys[$index]=$_;
      #printf "$keys[$index]\n";
      $index++;
    }
    close(sList);
    for($i=0;$i\n";
      system("grep -r 'Subject:.*$keyword.*' $ARGV[0] > wait4kill-s");
      open(killList,"./wait4kill-s");
      while(){
        if($_ =~ /^(.+):Subject:.*$/){
           printf "Deleting $1 ...\n";
               system("rm -f $1");
        }
      }
    close(killList);
    }
    system("rm -f ./wait4kill-s");
    ########## Starting 'From' feltering:
    open(fList,"${FList}") or die "Can't open ${FList}.\n";
    $index=0;
    while()
    {
      chop;
      $keys[$index]=$_;
      #printf "$keys[$index]\n";
      $index++;
    }
    close(fList);
    for($i=0;$i\n";
      system("grep -r 'From:.*$keyword.*' $ARGV[0] > wait4kill-f");
      open(killList,"./wait4kill-f");
      while(){
         if($_ =~ /^(.+):From:.*$/){
           printf "Deleting $1 ...\n";
               system("rm -f $1");
         }
      }
      close(killList);
    }
    system("rm -f ./wait4kill-f");
    ########## Starting 'NNTP-Posting-Host' feltering:
    open(hList,"${HList}") or die "Can't open ${HList}.\n";
    $index=0;
    while()
    {
      chop;
      $keys[$index]=$_;
      #printf "$keys[$index]\n";
      $index++;
    }
    close(hList);
    for($i=0;$i\n";
      system("grep -r 'NNTP-Posting-Host:.*$keyword.*' $ARGV[0] > wait4kill-h");
      open(killList,"./wait4kill-h");
      while(){
         if($_ =~ /^(.+):NNTP-Posting-Host:.*$/){
           printf "Deleting $1 ...\n";
               system("rm -f $1");
         }
      }
      close(killList);
    }
    system("rm -f ./wait4kill-h");
    然後您針對 script 所需在 /var/lib/suck 目錄下建立清單﹐將您要過濾的字串相應填上﹐逐行寫就是了。下面是各檔的內容﹕
    clist
    這是針對文章內容而設的。那麼凡是文章包含有此清單上面的字串都會被砍掉。這是威力最大的﹐也最容易誤砍無辜者﹐所以不要列太多名稱。我通常建議您把那些廣告者所宣傳的網站﹑電話﹑地址﹑單位名稱﹑等具“唯一性”的字眼寫在此檔。
    slist
    這是針對標題而設的。如果您想對所有標題中的字串進行過濾﹐就將可以寫在這裡。例如什麼﹕空片﹑情趣用品﹑無碼﹑等等。
    flist
    這是針對發信人名稱而設的。如果有人常用什麼宣傳王﹑佈告王﹑廣告王﹑片片俱樂部等名稱來發信的話﹐加在這裡就對了。
    hlist
    這是針對發信主機而設的。如果您用 outlook 的話﹐可以用鼠標右點廣告文章的標題﹐然後看“內容”﹔或是用 netscape 的新聞閱讀器看文章的“source”﹐就可以找到一個“NNTP-Posting-Host”的句子﹐冒號後面就是該發信主機了。除非對方用非固定的連線或用程式修改發信文章﹐那麼您可以把所有從這台主機所發的文件砍掉。
    如果您有 cross-post 的習慣﹐也就是一次過向不同的新聞群組發佈文章的話。不好意思﹐假如您要發佈的新聞群組中超過三個是用“tw”開頭的﹐就通不過這個 script了。不過﹐您可以修改其中關於 “Filtering Newsgroups”部份的 Regular Expression﹐以符合您的需求。
    上面那個 newsfil.pl 只要寫好﹐連同那些過濾清單檔一起放在 /var/lib/suck 目錄下面﹐那麼當執行 get.news.inn 的時候﹐就會被執行起來。不過﹐它除了可以用來砍每次 suck 下載時的信件。而且也用來清理特定目錄裡面的新聞郵件﹐包括子目錄哦。只要執行 ./newsfil.pl /the/path/of/dir 就可以了﹐但要小心哦﹕如果不是新聞檔的存放目錄﹐那麼﹐只要檔案裡面有相關字串的話﹐都一律會被砍掉哦~~~ 小心小心﹗
    好了﹐網中人把上面提到的相關檔案﹐都包在一個壓縮檔了。您只要
    點這裡
    將它下載回去﹐就可以慢慢針對自己的實際情形修改了。
    測試
    假如不牽涉餵信的問題﹐設定一個 NEWS 伺服器是非常簡單的﹐應該不至於有問題出現。不過﹐會得運用 inncheck -v 來檢查﹐會幫我們找到許多設定問題。不過有些東西﹐inncheck 也無能為力﹐例如﹐在 active 檔案裡面﹐留意是否要包含原來的那些群組﹐例如 control﹑control.cancel﹑juck 等幾個﹐別以為從上游抓下來的就可以代替哦。反而﹐newsgroups 那個檔案倒不是很重要﹐只要將群組描述清楚就可以了。
    當您完成一些設定之後﹐其實沒有必要一定重新啟動 innd 的。您可以執行 ctlinnd -h 看看有哪些動作可以做﹐比如﹐重新讀取 active 檔﹕
    ctlinnd reload active "update active only" 註﹕別少了最後那個 “reason”哦﹐就算您不想打字﹐也應該要有一對 " " 符號。
    不過﹐如果您真的需要重新啟動 innd ﹐我建議不要用 restart﹐而是先 stop 再 start﹐這還不夠﹐還要再輸入 service innd status 看看新的 innd 是否跑起來了。我發現就算顯示 start [ OK ] 之後也未必一定 OK 哦~~~
    在做餵信的時候﹐最關鍵是 newsfeeds 那個檔案﹐一定要留意格式是否寫對了﹐以及傳送模式(如Tf)和寫入信息(如Wnm)是否設對﹐這裡的設定要符合 nntpsend.ctl 的要求。我強烈建議您 man newsfeeds 看看啦。當然﹐還別忘了受方也要設定好 incoming.conf 哦。
    如果您要用 suck 來抓信和送信﹐要注意的地方是 get.news.inn 檔案裡面的 SITE= 要和 newsfeed 裡面設定的名稱一致。因為送信時是主要參考 /var/spool/news/outgoing 目錄下的名稱﹐它必須由 innd 產生﹐而供 suck 來讀取。要是在 post 過程中遇到問題﹐或許會在該目錄下產生一個 xxxx.new (xxxx 是 site 名稱)﹐這樣會造成往後的文章都不能 post。這時候﹐只要將那些 *.new 砍掉就是了。
    就算如此﹐最後有一點您還是最好留意一下的﹐就是看看跑完 get.inn.news 之後﹐您的 innd 是否能夠順利啟動。根據我這邊的經驗是﹐通常第一次跑 get.inn.news 之後﹐/var/lib/news/active 檔有可能給弄得亂七八糟﹐尤其是那些數字可能會超過或少過 10 位數﹔也有時候會把一些空白意外移除掉了。這些都會導至 innd 跑不起來﹐而且可惡的是執行 inncheck 並不能檢查出來。如果真的如此﹐我建議您“逐行”檢查 active 檔的準確性。
    還有﹐在我目前使用的版本和設定來實作﹐我發現在下游 post 的第一篇文章是無法用 suck 上載到上游群組中去的。不知道為什麼﹐不過只要從第一篇往後的回應文章(RE﹕)都可以就是了。怪怪的﹐如果您能幫我解決這問題的話﹐一定要告訴我哦~~~﹗(不過﹐後來在別的機器上試過又沒有﹐很怪啦~~)
    最後﹐如果您想對 NEWS 做更深入的了解﹐可以參閱 > 這篇文章。(我是從
    台大電機 Maxwell BBS 精華區
    看來的﹐雖然著作日期舊了一點﹐但絕對值得一讀﹗)


    本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/23724/showart_167535.html
  • 您需要登录后才可以回帖 登录 | 注册

    本版积分规则 发表回复

      

    北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
    未成年举报专区
    中国互联网协会会员  联系我们:huangweiwei@itpub.net
    感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

    清除 Cookies - ChinaUnix - Archiver - WAP - TOP