/tags/yaws-1-0/yaws/src/yaws_ctl.erl

https://github.com/babo/yaws · Erlang · 191 lines · 139 code · 42 blank · 10 comment · 3 complexity · 80c859f26f67fd9ab865aa38e17eeec4 MD5 · raw file

  1. %%%----------------------------------------------------------------------
  2. %%% File : yaws_ctl.erl
  3. %%% Author : Claes Wikstrom <klacke@bluetail.com>
  4. %%% Purpose :
  5. %%% Created : 29 Apr 2002 by Claes Wikstrom <klacke@bluetail.com>
  6. %%%----------------------------------------------------------------------
  7. %% some code to remoteley control a running yaws server
  8. -module(yaws_ctl).
  9. -author('klacke@bluetail.com').
  10. -compile(export_all).
  11. -include_lib("kernel/include/file.hrl").
  12. -include_lib("yaws/include/yaws.hrl").
  13. -include_lib("yaws/include/yaws_api.hrl").
  14. ctl_file("0") ->
  15. "/var/run/yaws.ctl";
  16. ctl_file(Id) ->
  17. io_lib:format("/tmp/yaws.ctl.~s",[Id]).
  18. start(Top, Id) ->
  19. case gen_tcp:listen(0, [{packet, 2},
  20. {active, false},
  21. binary,
  22. {ip, {127,0,0,1}},
  23. {reuseaddr, true}]) of
  24. {ok, L} ->
  25. case inet:sockname(L) of
  26. {ok, {_, Port}} ->
  27. F = ctl_file(Id),
  28. file:write_file(F, io_lib:format("~w", [Port])),
  29. {ok, FI} = file:read_file_info(F),
  30. M = FI#file_info.mode,
  31. M2 = M bor (8#00222),
  32. file:write_file_info(F, FI#file_info{mode = M2}), %%ign ret
  33. Top ! {self(), ok},
  34. aloop(L);
  35. Err ->
  36. error_logger:format("Cannot get sockname for ctlsock",[]),
  37. Top ! {self(), {error, Err}}
  38. end;
  39. Err ->
  40. error_logger:format("Cannot listen on ctl socket ",[]),
  41. Top ! {self(), {error, Err}}
  42. end.
  43. aloop(L) ->
  44. case gen_tcp:accept(L) of
  45. {ok, A} ->
  46. handle_a(A);
  47. _Err ->
  48. ignore
  49. end,
  50. aloop(L).
  51. handle_a(A) ->
  52. case gen_tcp:recv(A, 0) of
  53. {ok, Data} ->
  54. case binary_to_term(Data) of
  55. hup ->
  56. Res = yaws:dohup(A),
  57. Res;
  58. stop ->
  59. gen_tcp:send(A, "stopping\n"),
  60. init:stop();
  61. status ->
  62. a_status(A),
  63. gen_tcp:close(A);
  64. Other ->
  65. gen_tcp:send(A, io_lib:format("Other: ~p~n", [Other])),
  66. gen_tcp:close(A)
  67. end;
  68. _Err ->
  69. ignore
  70. end.
  71. f(Fmt, As) ->
  72. io_lib:format(Fmt, As).
  73. a_status(Sock) ->
  74. {UpTime, L} = yaws_server:stats(),
  75. {Days, {Hours, Minutes, _Secs}} = UpTime,
  76. H = f("~n Uptime: ~w Days, ~w Hours, ~w Minutes ~n",
  77. [Days, Hours, Minutes]),
  78. T =lists:map(
  79. fun({Host,IP,Hits}) ->
  80. L1= f("stats for ~p at ~p ~n",
  81. [Host,IP]),
  82. T = "\n"
  83. "URL Number of hits\n",
  84. L2=lists:map(
  85. fun({Url, Hits2}) ->
  86. f("~-30s ~-7w ~n",
  87. [Url, Hits2])
  88. end, Hits),
  89. END = "\n",
  90. [L1, T, L2, END]
  91. end, L),
  92. gen_tcp:send(Sock, [H, T]),
  93. %% Now lets' figure out the status of loaded modules
  94. ok.
  95. actl(Term, Uid) ->
  96. CtlFile = ctl_file(Uid),
  97. case file:read_file(CtlFile) of
  98. {ok, B} ->
  99. L = binary_to_list(B),
  100. I = list_to_integer(L),
  101. case gen_tcp:connect({127,0,0,1}, I,
  102. [{active, false},
  103. {reuseaddr, true},
  104. binary,
  105. {packet, 2}]) of
  106. {ok, Fd} ->
  107. gen_tcp:send(Fd, term_to_binary(Term)),
  108. Res = gen_tcp:recv(Fd, 0),
  109. case Res of
  110. {ok, Bin} ->
  111. io:format("~s~n", [binary_to_list(Bin)]);
  112. Err ->
  113. io:format("yaws server for uid ~s not responding: ~p ~n",[Uid, Err])
  114. end,
  115. gen_tcp:close(Fd),
  116. Res;
  117. Err ->
  118. io:format("yaws server under uid ~s not running \n", [Uid]),
  119. Err
  120. end;
  121. Err ->
  122. io:format("yaws: Cannot open runfile ~s ... server under uid ~s "
  123. "not running ?? ~n",
  124. [CtlFile, Uid])
  125. end,
  126. init:stop().
  127. uid() ->
  128. os:cmd("id -u") -- [10].
  129. %% send a hup (kindof) to the yaws server to make it
  130. %% reload its configuration and clear its caches
  131. hup() ->
  132. actl(hup, uid()).
  133. stop() ->
  134. actl(stop, uid()).
  135. status() ->
  136. actl(status, uid()).
  137. check([File| IncludeDirs]) ->
  138. GC = yaws_config:make_default_gconf(false),
  139. GC2 = GC#gconf{include_dir = lists:map(fun(X) -> atom_to_list(X) end,
  140. IncludeDirs)},
  141. SC = #sconf{},
  142. case yaws_compile:compile_file(atom_to_list(File), GC2, SC) of
  143. {ok, [{errors, 0}| _Spec]} ->
  144. io:format("ok~n",[]),
  145. init:stop();
  146. _Other ->
  147. io:format("~nErrors in ~p~n", [File]),
  148. init:stop()
  149. end.