11const { exec } = require ( 'child_process' )
22const Client = require ( 'ssh2' ) . Client
3- const scpClient = require ( 'scp2' )
43const { URL } = require ( 'url' )
54const http = require ( 'http' )
65const https = require ( 'https' )
@@ -274,26 +273,49 @@ class VRouter {
274273 await this . wait ( 10000 )
275274
276275 await this . installPackage ( )
277- this . process . emit ( 'build' , '更新软件源并安装必要软件包, 请稍候60秒' )
278- await this . wait ( 60000 )
276+ this . process . emit ( 'build' , '更新软件源并安装必要软件包, 请稍候20-60秒' )
277+ await this . wait ( 20000 )
278+ // return this.serialLog('done: install package && restart dropbear')
279+
280+ let remote
281+ let retry = - 1
282+ while ( true ) {
283+ try {
284+ retry += 1
285+ remote = await this . connect ( )
286+ const output = await remote . remoteExec ( 'tail -n 1 /vrouter.log' )
287+ if ( output === 'done: install package && restart dropbear' ) {
288+ winston . debug ( '安装软件包完成' )
289+ this . process . emit ( 'build' , '安装软件包完成' )
290+ break
291+ } else {
292+ throw Error ( '未完成' )
293+ }
294+ } catch ( err ) {
295+ if ( retry >= 4 ) {
296+ throw Error ( '未能安装软件包, 请确保网络通畅后重试' )
297+ }
298+ winston . debug ( '安装软件包未完成, 10秒后重试' )
299+ // this.process.emit('buid', '无法登录到虚拟机, 10秒后重试')
300+ await this . wait ( 10000 )
301+ }
302+ }
303+ this . process . emit ( 'build' , '成功登录虚拟机' )
304+ await this . serialLog ( 'done: connect to vm' )
279305
280306 const src = path . join ( __dirname , '..' , 'third_party' )
281307 const dst = this . config . vrouter . configDir + '/third_party/'
282- await this . scp ( src , dst )
308+ await remote . scp ( src , dst )
283309 . catch ( ( error ) => {
284310 throw error
285311 } )
286312 this . process . emit ( 'build' , '拷贝 shadowsocks[r] 以及 kcptun 到虚拟机' )
287313 await this . serialLog ( 'done: scp third_party' )
288314
289- await this . scpConfigAll ( )
315+ await remote . scpConfigAll ( )
290316 this . process . emit ( 'build' , '拷贝配置文件到虚拟机' )
291317 await this . serialLog ( 'done: scpConfigAll' )
292318
293- const remote = await this . connect ( )
294- this . process . emit ( 'build' , '登录虚拟机' )
295- await this . serialLog ( 'done: connect to vm' )
296-
297319 await remote . installKt ( )
298320 await this . serialLog ( 'done: installKt' )
299321 this . process . emit ( 'build' , '安装 kcptun' )
@@ -1495,10 +1517,10 @@ class VRouter {
14951517 this . config = newCfg
14961518
14971519 const thirdParty = path . join ( __dirname , '..' , 'third_party' )
1498- await this . scp ( `${ thirdParty } /ssr-tunnel` , '/usr/bin/' )
1499- await this . scp ( `${ thirdParty } /ssr-redir` , '/usr/bin/' )
15001520 const remote = await this . connect ( )
1501- await this . remoteExec ( 'chmod +x /usr/bin/ssr-*' )
1521+ await remote . scp ( `${ thirdParty } /ssr-tunnel` , '/usr/bin/' )
1522+ await remote . scp ( `${ thirdParty } /ssr-redir` , '/usr/bin/' )
1523+ await remote . remoteExec ( 'chmod +x /usr/bin/ssr-*' )
15021524 await remote . remoteExec ( 'opkg update && opkg install libopenssl' )
15031525 await remote . service ( 'shadowsocks' , 'stop' ) . catch ( ( ) => { } )
15041526 await remote . service ( 'kcptun' , 'stop' ) . catch ( ( ) => { } )
@@ -1508,27 +1530,6 @@ class VRouter {
15081530 }
15091531 return this . saveCfg2File ( )
15101532 }
1511- async scp ( src , dst ) {
1512- if ( ! src ) {
1513- throw Error ( 'must specify src for scp' )
1514- }
1515- let dest = dst || this . config . vrouter . configDir
1516- const opt = {
1517- host : this . config . vrouter . ip ,
1518- username : this . config . vrouter . username ,
1519- password : this . config . vrouter . password ,
1520- path : dest
1521- }
1522- return new Promise ( ( resolve , reject ) => {
1523- scpClient . scp ( src , opt , ( err ) => {
1524- if ( err ) {
1525- reject ( err )
1526- } else {
1527- resolve ( dest )
1528- }
1529- } )
1530- } )
1531- }
15321533 async copyTemplate ( fileName ) {
15331534 const template = path . join ( __dirname , '..' , 'config' , fileName )
15341535 const dest = path . join ( this . config . host . configDir , fileName )
@@ -1541,91 +1542,6 @@ class VRouter {
15411542 return dest
15421543 }
15431544 }
1544- async scpConfig ( type = 'shadowsocks' , overwrite = false ) {
1545- let p
1546- switch ( type ) {
1547- case 'tunnelDnsService' :
1548- p = await this . generateService ( 'tunnelDns' )
1549- await this . scp ( p , '/etc/init.d/' )
1550- await this . serialExec ( `chmod +x /etc/init.d/${ this . config . tunnelDns . service } ` )
1551- break
1552- case 'ssService' :
1553- p = await this . generateService ( 'shadowsocks' )
1554- await this . scp ( p , '/etc/init.d/' )
1555- await this . serialExec ( `chmod +x /etc/init.d/${ this . config . shadowsocks . service } ` )
1556- break
1557- case 'ssrService' :
1558- p = await this . generateService ( 'shadowsocksr' )
1559- await this . scp ( p , '/etc/init.d/' )
1560- await this . serialExec ( `chmod +x /etc/init.d/${ this . config . shadowsocksr . service } ` )
1561- break
1562- case 'ktService' :
1563- p = await this . generateService ( 'kcptun' )
1564- winston . debug ( `generateService-kcptun for proxies: ${ this . config . firewall . currentProxies } ` )
1565- await this . scp ( p , '/etc/init.d/' )
1566- await this . serialExec ( `chmod +x /etc/init.d/${ this . config . kcptun . service } ` )
1567- break
1568- case 'tunnelDns' :
1569- case 'shadowsocks' :
1570- case 'shadowsocksr' :
1571- case 'kcptun' :
1572- p = await this . generateConfig ( type )
1573- for ( let i = 0 ; i < p . length ; i ++ ) {
1574- await this . scp ( p [ i ] , this . config . vrouter . configDir )
1575- }
1576- break
1577- case 'dnsmasq' :
1578- p = await this . generateDnsmasqCf ( overwrite )
1579- await this . scp ( p , '/etc/dnsmasq.d/' )
1580- break
1581- case 'ipset' :
1582- p = await this . generateIPsets ( overwrite )
1583- winston . debug ( 'generated ipset' )
1584- await this . scp ( p , this . config . vrouter . configDir )
1585- break
1586- case 'firewall' :
1587- p = await this . generateFWRules ( null , null , overwrite )
1588- await this . scp ( p , '/etc/' )
1589- break
1590- case 'watchdog' :
1591- p = await this . generateWatchdog ( )
1592- await this . scp ( p , this . config . vrouter . configDir )
1593- await this . serialExec ( `chmod +x ${ this . config . vrouter . configDir } /${ this . config . firewall . watchdogFile } ` )
1594- break
1595- case 'cron' :
1596- p = await this . generateCronJob ( )
1597- await this . scp ( p , this . config . vrouter . configDir )
1598- break
1599- }
1600- }
1601- async scpConfigAll ( overwrite ) {
1602- const types = [
1603- 'dnsmasq' ,
1604- 'ipset' ,
1605- 'firewall' ,
1606- 'watchdog' ,
1607- 'cron'
1608- ]
1609- if ( this . config . firewall . enableTunnelDns ) {
1610- types . push ( 'tunnelDnsService' )
1611- types . push ( 'tunnelDns' )
1612- }
1613- const proxies = this . config . firewall . currentProxies
1614- if ( proxies . includes ( 'Kt' ) ) {
1615- types . push ( 'kcptun' )
1616- types . push ( 'ktService' )
1617- }
1618- if ( proxies . substr ( 0 , 3 ) === 'ssr' ) {
1619- types . push ( 'shadowsocksr' )
1620- types . push ( 'ssrService' )
1621- } else if ( proxies . substr ( 0 , 2 ) === 'ss' ) {
1622- types . push ( 'shadowsocks' )
1623- types . push ( 'ssService' )
1624- }
1625- for ( let i = 0 ; i < types . length ; i += 1 ) {
1626- await this . scpConfig ( types [ i ] , overwrite )
1627- }
1628- }
16291545 async connect ( startFirst ) {
16301546 const state = await this . getvmState ( )
16311547 if ( state !== 'running' ) {
@@ -1634,7 +1550,13 @@ class VRouter {
16341550 return new Promise ( ( resolve , reject ) => {
16351551 const conn = new Client ( )
16361552 conn . on ( 'ready' , ( ) => {
1637- resolve ( new VRouterRemote ( conn , this . config , this ) )
1553+ conn . sftp ( ( err , sftp ) => {
1554+ if ( err ) {
1555+ reject ( err )
1556+ } else {
1557+ resolve ( new VRouterRemote ( conn , sftp , this . config , this ) )
1558+ }
1559+ } )
16381560 } ) . connect ( {
16391561 host : this . config . vrouter . ip ,
16401562 port : this . config . vrouter . port ,
0 commit comments