action.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. <?php
  2. if(!DEFINED('EGP'))
  3. exit(header('Refresh: 0; URL=http://'.$_SERVER['SERVER_NAME'].'/404'));
  4. include(LIB.'control/actions.php');
  5. class action extends actions
  6. {
  7. public static function start($id, $type = 'start')
  8. {
  9. global $cfg, $sql, $user, $start_point;
  10. $sql->query('SELECT `uid`, `unit`, `game`, `address`, `slots`, `name`, `tickrate`, `map_start`, `vac`, `time_start`, `core_fix`, `pingboost` FROM `control_servers` WHERE `id`="'.$id.'" LIMIT 1');
  11. $server = $sql->get();
  12. include(LIB.'ssh.php');
  13. $sql->query('SELECT `address`, `passwd`, `fcpu` FROM `control` WHERE `id`="'.$server['unit'].'" LIMIT 1');
  14. $unit = $sql->get();
  15. // Проверка ssh соедниения пу с локацией
  16. if(!$ssh->auth($unit['passwd'], $unit['address']))
  17. return array('e' => sys::text('error', 'ssh'));
  18. list($ip, $port) = explode(':', $server['address']);
  19. // Убить процессы
  20. $ssh->set('kill -9 `ps aux | grep s_'.$server['uid'].' | grep -v grep | awk '."'{print $2}'".' | xargs;'
  21. .'lsof -i@'.$server['address'].' | awk '."'{print $2}'".' | grep -v PID | xargs`; sudo -u server'.$server['uid'].' screen -wipe');
  22. $taskset = '';
  23. // Если включена система автораспределения и не установлен фиксированный поток
  24. if(!$server['core_fix'])
  25. {
  26. $proc_stat = array();
  27. $proc_stat[0] = $ssh->get('cat /proc/stat');
  28. }
  29. // Проверка наличия стартовой карты
  30. $ssh->set('cd /servers/'.$server['uid'].'/csgo/maps/ && du -ah | grep -e "\.bsp$" | awk \'{print $2}\'');
  31. include_once(LIB.'games/games.php');
  32. if(games::map($server['map_start'], $ssh->get()))
  33. return array('e' => sys::updtext(sys::text('servers', 'nomap'), array('map' => $server['map_start'].'.bsp')));
  34. // Если система автораспределения продолжить парсинг загрузки процессора
  35. if(isset($proc_stat))
  36. {
  37. $proc_stat[1] = $ssh->get('cat /proc/stat');
  38. // Ядро/поток, на котором будет запущен игровой сервер (поток выбран с рассчетом наименьшей загруженности в момент запуска игрового сервера)
  39. $core = sys::cpu_idle($proc_stat, $server['unit'], $unit['fcpu'], true); // число от 1 до n (где n число ядер/потоков в процессоре (без нулевого)
  40. if(!is_numeric($core))
  41. return array('e' => sys::text('error', 'cpu'));
  42. $taskset = 'taskset -c '.$core;
  43. }
  44. if($server['core_fix'])
  45. {
  46. $core = $server['core_fix']-1;
  47. $taskset = 'taskset -c '.$core;
  48. }
  49. // Античит VAC
  50. $vac = $server['vac'] == 0 ? '-insecure' : '-secure';
  51. // TV
  52. $tv = $server['tv'] ? '+tv_enable 1 +tv_maxclients 30 +tv_port '.($port+10000) : '-nohltv';
  53. $check = explode('/', $server['map_start']);
  54. // Стартовая карта
  55. $map = $check[0] == 'workshop' ? '+workshop_start_map '.$check[1] : '+map \''.$server['map_start'].'\'';
  56. // Игровой режим
  57. $mods = array(
  58. 1 => '+game_type 0 +game_mode 0',
  59. 2 => '+game_type 0 +game_mode 1',
  60. 3 => '+game_type 1 +game_mode 0',
  61. 4 => '+game_type 1 +game_mode 1',
  62. 5 => '+game_type 1 +game_mode 2'
  63. );
  64. $mod = !$server['pingboost'] ? $mods[2] : $mods[$server['pingboost']];
  65. // Параметры запуска
  66. $bash = './srcds_run -debug -game csgo -norestart -condebug console.log -usercon -tickrate '.$server['tickrate'].' '.$mod.' +servercfgfile server.cfg '.$map.' -maxplayers_override '.$server['slots'].' +ip '.$ip.' +net_public_adr '.$ip.' +port '.$port.' -sv_lan 0 '.$vac.' '.$tv;
  67. // Временный файл
  68. $temp = sys::temp($bash);
  69. // Обновление файла start.sh
  70. $ssh->setfile($temp, '/servers/'.$server['uid'].'/start.sh', 0500);
  71. // Строка запуска
  72. $ssh->set('cd /servers/'.$server['uid'].';' // переход в директорию игрового сервера
  73. .'rm *.pid;' // Удаление *.pid файлов
  74. .'sudo -u server'.$server['uid'].' mkdir -p csgo/oldstart;' // Создание папки логов
  75. .'cat csgo/console.log >> csgo/oldstart/'.date('d.m.Y_H:i:s', $server['time_start']).'.log; rm csgo/console.log; rm csgo/oldstart/01.01.1970_03:00:00.log;' // Перемещение лога предыдущего запуска
  76. .'chown server'.$server['uid'].':1000 start.sh;' // Обновление владельца файла start.sh
  77. .'sudo -u server'.$server['uid'].' screen -dmS s_'.$server['uid'].' '.$taskset.' sh -c "./start.sh"'); // Запуск игровго сервера
  78. $core = !isset($core) ? 0 : $core+1;
  79. // Обновление информации в базе
  80. $sql->query('UPDATE `control_servers` set `status`="'.$type.'", `online`="0", `players`="", `core_use`="'.$core.'", `time_start`="'.$start_point.'", `stop`="1" WHERE `id`="'.$id.'" LIMIT 1');
  81. unlink($temp);
  82. // Сброс кеша
  83. actions::clmcache($id);
  84. sys::reset_mcache('ctrl_server_scan_mon_pl_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => $type, 'online' => 0, 'players' => ''));
  85. sys::reset_mcache('ctrl_server_scan_mon_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => $type, 'online' => 0));
  86. return array('s' => 'ok');
  87. }
  88. public static function change($id, $map = false)
  89. {
  90. global $cfg, $sql, $html, $user, $mcache;
  91. // Если в кеше есть карты
  92. if($mcache->get('ctrl_server_maps_change_'.$id) != '' AND !$map)
  93. return array('maps' => $mcache->get('ctrl_server_maps_change_'.$id));
  94. include(LIB.'ssh.php');
  95. include(LIB.'games/games.php');
  96. $sql->query('SELECT `uid`, `unit`, `game`, `online`, `players`, `name` FROM `control_servers` WHERE `id`="'.$id.'" LIMIT 1');
  97. $server = $sql->get();
  98. $sql->query('SELECT `address`, `passwd` FROM `control` WHERE `id`="'.$server['unit'].'" LIMIT 1');
  99. $unit = $sql->get();
  100. // Проверка ssh соедниения пу с локацией
  101. if(!$ssh->auth($unit['passwd'], $unit['address']))
  102. return array('e' => sys::text('error', 'ssh'));
  103. // Массив карт игрового сервера (папка "maps")
  104. $aMaps = explode("\n", $ssh->get('cd /servers/'.$server['uid'].'/csgo/maps/ && du -ah | grep -e "\.bsp$" | awk \'{print $2}\''));
  105. // Удаление пустого элемента
  106. unset($aMaps[count($aMaps)-1]);
  107. // Удаление ".bsp"
  108. $aMaps = str_ireplace(array('./', '.bsp'), '', $aMaps);
  109. // Если выбрана карта
  110. if($map)
  111. {
  112. $map = str_replace('|', '/', $map);
  113. // Проверка наличия выбранной карты
  114. if(games::map($map, $aMaps))
  115. return array('e' => sys::updtext(sys::text('servers', 'change'), array('map' => $map.'.bsp')));
  116. // Отправка команды changelevel
  117. $ssh->set('sudo -u server'.$server['uid'].' screen -p 0 -S s_'.$server['uid'].' -X eval '."'stuff \"changelevel ".sys::cmd($map)."\"\015'");
  118. // Обновление информации в базе
  119. $sql->query('UPDATE `control_servers` set `status`="change" WHERE `id`="'.$id.'" LIMIT 1');
  120. // Сброс кеша
  121. actions::clmcache($id);
  122. sys::reset_mcache('ctrl_server_scan_mon_pl_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'change', 'online' => $server['online'], 'players' => base64_decode($server['players'])));
  123. sys::reset_mcache('ctrl_server_scan_mon_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'change', 'online' => $server['online']));
  124. return array('s' => 'ok');
  125. }
  126. // Сортировка списка карт
  127. sort($aMaps);
  128. reset($aMaps);
  129. // Генерация списка карт для выбора
  130. foreach($aMaps as $map)
  131. {
  132. $aName = explode('/', $map);
  133. $name = end($aName);
  134. $html->get('change_list', 'sections/control/servers/csgo');
  135. $html->set('img', file_exists(DIR.'/maps/'.$server['game'].'/'.$name.'.jpg') ? $cfg['http'].'maps/'.$server['game'].'/'.$name.'.jpg' : $cfg['http'].'template/images/status/none.jpg');
  136. $html->set('map', str_replace('/', '|', $map));
  137. $html->set('name', $name);
  138. $html->set('id', $server['unit']);
  139. $html->set('server', $id);
  140. if(count($aName) > 1)
  141. $html->unit('workshop', true);
  142. else
  143. $html->unit('workshop');
  144. $html->pack('maps');
  145. }
  146. // Запись карт в кеш
  147. $mcache->set('ctrl_server_maps_change_'.$id, $html->arr['maps'], false, 60);
  148. return array('maps' => $html->arr['maps']);
  149. }
  150. public static function update($id)
  151. {
  152. global $cfg, $sql, $user, $start_point;
  153. include(LIB.'ssh.php');
  154. $sql->query('SELECT `uid`, `unit`, `game`, `name`, `ftp`, `core_fix` FROM `control_servers` WHERE `id`="'.$id.'" LIMIT 1');
  155. $server = $sql->get();
  156. $sql->query('SELECT `address`, `passwd`, `sql_login`, `sql_passwd`, `sql_port`, `sql_ftp`, `fcpu` FROM `control` WHERE `id`="'.$server['unit'].'" LIMIT 1');
  157. $unit = $sql->get();
  158. // Проверка ssh соедниения пу с локацией
  159. if(!$ssh->auth($unit['passwd'], $unit['address']))
  160. return array('e' => sys::text('error', 'ssh'));
  161. $taskset = '';
  162. // Если включена система автораспределения и не установлен фиксированный поток
  163. if(!$server['core_fix'])
  164. {
  165. $proc_stat = array();
  166. $proc_stat[0] = $ssh->get('cat /proc/stat');
  167. }
  168. // Директория игрового сервера
  169. $install = '/servers/'.$server['uid'];
  170. // Если система автораспределения продолжить парсинг загрузки процессора
  171. if(isset($proc_stat))
  172. {
  173. $proc_stat[1] = $ssh->get('cat /proc/stat');
  174. // Ядро/поток, на котором будет запущен игровой сервер (поток выбран с рассчетом наименьшей загруженности в момент запуска игрового сервера)
  175. $core = sys::cpu_idle($proc_stat, $server['unit'], $unit['fcpu'], true); // число от 1 до n (где n число ядер/потоков в процессоре (без нулевого)
  176. if(!is_numeric($core))
  177. return array('e' => 'Не удается выполнить операцию, нет свободного потока.');
  178. $taskset = 'taskset -c '.$core;
  179. }
  180. if($server['core_fix'])
  181. {
  182. $core = $server['core_fix']-1;
  183. $taskset = 'taskset -c '.$core;
  184. }
  185. $ssh->set('cd '.$cfg['steamcmd'].' && '.$taskset.' screen -dmS u_'.$server['uid'].' sh -c "'
  186. .'./steamcmd.sh +login anonymous +force_install_dir "'.$install.'" +app_update 740 +quit;'
  187. .'cd '.$install.';'
  188. .'chown -R server'.$server['uid'].':servers .;'
  189. .'find . -type d -exec chmod 700 {} \;;'
  190. .'find . -type f -exec chmod 600 {} \;;'
  191. .'chmod 500 '.params::$aFileGame[$server['game']].'"');
  192. $core = !isset($core) ? 0 : $core+1;
  193. // Обновление информации в базе
  194. $sql->query('UPDATE `control_servers` set `status`="update", `core_use`="'.$core.'" WHERE `id`="'.$id.'" LIMIT 1');
  195. // Сброс кеша
  196. actions::clmcache($id);
  197. sys::reset_mcache('ctrl_server_scan_mon_pl_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'update', 'online' => 0, 'players' => ''));
  198. sys::reset_mcache('ctrl_server_scan_mon_'.$id, $id, array('name' => $server['name'], 'game' => $server['game'], 'status' => 'update', 'online' => 0));
  199. return array('s' => 'ok');
  200. }
  201. }
  202. ?>