The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
Changes 25104
LICENSE 44
MANIFEST 05
META.yml 26
Makefile.PL 1129
README 22
README.md 16
bin/ubic 611
bin/ubic-admin 44
bin/ubic-daemon 54
bin/ubic-periodic 44
bin/ubic-update 54
bin/ubic-watchdog 47
dist.ini 11
lib/Ubic/AccessGuard.pm 55
lib/Ubic/Admin/Setup.pm 1763
lib/Ubic/AtomicFile.pm 44
lib/Ubic/Cmd/Results.pm 54
lib/Ubic/Cmd.pm 98
lib/Ubic/Credentials/OS/MacOSX.pm 55
lib/Ubic/Credentials/OS/POSIX.pm 77
lib/Ubic/Credentials/OS/Windows.pm 44
lib/Ubic/Credentials.pm 44
lib/Ubic/Daemon/OS/Linux.pm 44
lib/Ubic/Daemon/OS/POSIX.pm 56
lib/Ubic/Daemon/OS.pm 44
lib/Ubic/Daemon/PidState.pm 55
lib/Ubic/Daemon/Status.pm 416
lib/Ubic/Daemon.pm 1792
lib/Ubic/Lockf/Alarm.pm 44
lib/Ubic/Lockf.pm 76
lib/Ubic/Logger.pm 54
lib/Ubic/Manual/FAQ.pod 68
lib/Ubic/Manual/Intro.pod 43
lib/Ubic/Manual/Multiservices.pod 43
lib/Ubic/Manual/Overview.pod 43
lib/Ubic/Multiservice/Dir.pm 44
lib/Ubic/Multiservice/Simple.pm 54
lib/Ubic/Multiservice.pm 54
lib/Ubic/Persistent.pm 44
lib/Ubic/Ping/Service.pm 55
lib/Ubic/Ping.pm 1625
lib/Ubic/PortMap.pm 54
lib/Ubic/Result/Class.pm 510
lib/Ubic/Result.pm 54
lib/Ubic/Run.pm 44
lib/Ubic/Service/Common.pm 55
lib/Ubic/Service/SimpleDaemon.pm 1885
lib/Ubic/Service/Skeleton.pm 65
lib/Ubic/Service/Utils.pm 54
lib/Ubic/Service.pm 717
lib/Ubic/ServiceLoader/Base.pm 44
lib/Ubic/ServiceLoader/Default.pm 44
lib/Ubic/ServiceLoader/Ext/ini.pm 44
lib/Ubic/ServiceLoader/Ext/json.pm 44
lib/Ubic/ServiceLoader.pm 44
lib/Ubic/Settings/ConfigFile.pm 55
lib/Ubic/Settings.pm 44
lib/Ubic/SingletonLock.pm 44
lib/Ubic/UA.pm 55
lib/Ubic/Watchdog.pm 512
lib/Ubic.pm 1121
redhat/perl-Ubic.spec 076
root_t/daemon.t 11
root_t/root.t 11
t/00_compile.t 11
t/author-ping.t 1414
t/credentials.t 013
t/logrotate.t 051
t/service/autostart/sleeping-daemon-autostart 07
t/setup.t 35
t/simple-daemon.t 356
t/ubic-script.t 11
t/watchdog-autostart.t 038
t/watchdog.t 25
75 files changed (This is a version diff) 386977
@@ -1,5 +1,84 @@
 Revision history for Ubic
 
+1.58    2015-01-28
+    * SimpleDaemon: customizable stop_timeout
+    (thanks to github:nwtour for the patch, see https://github.com/berekuk/Ubic/pull/73)
+    * SimpleDaemon: sigusr1 and sigusr2 custom commands
+    (thanks to github:bacek for the patch, see https://github.com/berekuk/Ubic/pull/70)
+    * Ubic::Ping - check via 127.0.0.1 instead of localhost
+    (thanks to github:eightn for the patch, see https://github.com/berekuk/Ubic/pull/71)
+
+1.57_01 2014-08-11
+    * fix Ubic::Credentials::OS::POSIX 'eq' method
+
+1.57    2013-11-21
+    * fix various documentation typos
+    (thanks to github:dsteinbrunner and github:akarelas for patches)
+    * modernize Ubic::Ping to respond with http 1.1 message and a proper content-type header
+    (thanks to github:alnewkirk)
+
+1.56    2013-07-30
+    * Reformatted Changes as per CPAN::Changes::Spec
+    (thanks to github:sergeyromanov for the patch, see https://github.com/berekuk/Ubic/pull/55)
+
+1.55    2013-07-26
+    * support PERLBREW_ROOT
+    (thanks to github:spacebat for the patch, see https://github.com/berekuk/Ubic/pull/54)
+
+1.54    2013-05-28
+    * 'auto_start' option in Ubic::Service and SimpleDaemon
+
+1.53    2013-05-18
+    * fix crontab generation on setup!
+
+1.52    2013-05-12
+    * always add /usr/local/bin to $PATH
+
+1.51    2013-04-14
+    * autoflush stdout and stdin in ubic-guardian
+      (especially when we're proxying daemon's logs)
+
+1.50_01 2013-04-03
+    * support 'term_timeout' option in SimpleDaemon
+
+1.49    2013-03-13
+    * stable release, no code changes
+
+1.48_02 2013-02-26
+    * 'ubic status' exits with status code 0 if there're disabled services
+
+1.48_01 2013-01-31
+    * guardian supports logs proxying and reopening them on SIGHUP
+     (see https://github.com/berekuk/Ubic/pull/47)
+    * hint about 'ubic help' on unknown command
+
+1.48    2012-12-07
+    * detect ubic-watchdog location and put its full path to the crontab on setup
+    * 'ubic help' command (see https://github.com/berekuk/Ubic/issues/31)
+
+1.47    2012-12-03
+    * compatibility with perl 5.17 hash randomization
+     (see https://github.com/berekuk/Ubic/issues/45)
+    * append watchdog logs in crontab (instead of rewriting)
+
+1.46    2012-11-08
+    * require modern BSD::Resource version
+      (see https://github.com/berekuk/Ubic/issues/43)
+    * relax timing conditions in t/watchdog.t
+
+1.45    2012-11-01
+    * more robust t/simple-daemon.t
+
+1.44_03 2012-10-30
+    * setup process now offers auto-configuration
+    * typo fix in crontab code (thanks to Anton Ukolov)
+
+1.44_02 2012-10-30
+    * Solaris compatibility (thanks to Martin Schultheis!)
+
+1.44_01 2012-08-02
+    * support perlbrew, custom PATH and custom PELR5LIB
+
 1.44    2012-06-21
     * stable release, no code changes
 
@@ -190,26 +269,26 @@ Revision history for Ubic
          - Ubic::Daemon::OS modules family for OS-specific daemonization tasks
          - Ubic::Credentials::OS modules family for OS-specific user/group tasks
 
-1.24    Wed Feb 23, 2011
+1.24    2011-02-23
         * ubic-watchdog: change process name while checking specific service
         * check that uid change was successful before calling service action methods
         * default check_timeout() lowered from 10 minutes to 1 minute
 
-1.23    Thu Dec 02, 2010
+1.23    2010-12-02
         * ubic-ping: 404 message content fixed
         * ubic-watchdog:
          - set check_timeout alarm a bit earlier
          - another alarm before compiling services
 
-1.22    Sun Nov 07, 2010
+1.22    2010-11-07
         * Ubic::Multiservice:
          - default implementation of 'has_simple_service' method
          - POD improvements
 
-1.21_01 Thu Oct 21, 2010
+1.21_01 2010-10-21
         * fixed races in t/daemon.t
 
-1.21    Tue Oct 19, 2010
+1.21    2010-10-19
         * Ubic.pm:
          - set_ubic_dir() renamed to set_data_dir()
          (set_ubic_dir still remains in code for backward compatibility)
@@ -225,25 +304,25 @@ Revision history for Ubic
         * deprecated Ubic::Catalog module removed (it was renamed into Ubic::Multiservice long time ago)
 
 
-1.20    Wed Oct 13, 2010
+1.20    2010-10-13
         * documentation improvements
 
-1.19    Tue Sep 14, 2010
+1.19    2010-09-14
         * ubic-watchdog always uses Ubic->status interface to check service status
 
-1.18    Tue Sep 14, 2010
+1.18    2010-09-14
         * critical bugfix: ubic-watchdog correctly interpret extended statuses
         (thanks to Sawyer X for noticing this, see http://github.com/berekuk/Ubic/issues#issue/7)
         * Ubic::Lockf::Alarm moved to separate file, so PODs are now correct
 
-1.17    Mon Sep 13, 2010
+1.17    2010-09-13
         * Ubic::Run: recognize RedHat init script names
         (thanks to Sawyer X for the patch, see http://github.com/berekuk/Ubic/issues/#issue/5)
         * test improvements:
          - ubic-ping uses Config.pm to determine full perl binary path
          - memory-leak.t is more robust
 
-1.16    Tue Sep 07, 2010
+1.16    2010-09-07
         * Ubic::Daemon:
          - check_daemon() now returns proper Ubic::Daemon::Status object
          - don't log warning if daemon exited by sigterm
@@ -254,17 +333,17 @@ Revision history for Ubic
          - watchdog.t skips all tests if 'fakeroot' is not present
         * Ubic::Cmd: print 'running' result as good when it contains extended message
 
-1.15    Mon Sep 06, 2010
+1.15    2010-09-06
         * tests fixed to work under root user (http://github.com/berekuk/Ubic/issues#issue/4)
 
-1.14    Thu Sep 02, 2010
+1.14    2010-09-02
         * handle supplementary groups correctly
         * ubic-watchdog doesn't require root privileges anymore (unless service requires them, of course)
         * repo and bugtracker resources in META.yml
         * PodWeaver in dist.ini config, so all modules now have proper AUTHOR and COPYRIGHT sections
         * SimpleDaemon and Common services accept arrayref as 'group' value
 
-1.13    Wed Sep 01, 2010
+1.13    2010-09-01
         * Perl6::Slurp removed from dependencies
         * Ubic::Manual::FAQ now is actually added
         * group() method in services:
@@ -272,46 +351,46 @@ Revision history for Ubic
          - ubic will call setgid() before invoking any service methods
          - default group list consists only of main user's group, as returned by getpwnam; supplementary groups are not supported yet
 
-1.12    Thu Aug 26, 2010
+1.12    2010-08-26
         * Ubic::Manual::FAQ with first 2 questions
         * Ubic::Log documentation updated according to 1.11 changes
 
-1.11    Thu Aug 26, 2010
+1.11    2010-08-26
         * ubic-watchdog prints errors to stdout only
 
-1.10    Wed Aug 18, 2010
+1.10    2010-08-18
         * security bugfix: store all statuses in JSON format
 
-1.09    Thu Aug 12, 2010
+1.09    2010-08-12
         * bugfix: custom commands print 'ok' using green color and exit with zero
         code when there are not errors
 
-1.08    Tue Aug 03, 2010
+1.08    2010-08-03
         * bugfix: has_service for nested unexistent services
         * debian/ dir in distribution too
 
-1.07    Fri Jul 30, 2010
+1.07    2010-07-30
         * localize $@ in destructors
         * Ubic::Cmd refactoring, more consistent console results printing
 
-1.06    Fri Jun 18, 2010
+1.06    2010-06-18
         * using $Config{perlpath} in tests - should fix CPAN tests
         * Dist::Zilla
 
-1.05    Sun Jun 13, 2010
+1.05    2010-06-13
         MANIFEST up-to-date.
         Small POD improvements.
 
-1.04    Tue May 25, 2010
+1.04    2010-05-25
         - important bugfix: service locks fixed!
         - Ubic::Daemon: join all bin args if bin is arrayref.
         - Remove old configs from old yandex-ubic package.
 
-1.02    Tue May 4, 2010
+1.02    2010-05-04
         Remove old configs from old yandex-ubic package.
 
-1.01    Thu Apr 29, 2010
+1.01    2010-04-29
         Just fixing debian dependency issues.
 
-1.00    Wed Apr 28, 2010
+1.00    2010-04-28
         First opensource release.
@@ -1,4 +1,4 @@
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
@@ -12,7 +12,7 @@ b) the "Artistic License"
 
 --- The GNU General Public License, Version 1, February 1989 ---
 
-This software is Copyright (c) 2012 by Yandex LLC.
+This software is Copyright (c) 2015 by Yandex LLC.
 
 This is free software, licensed under:
 
@@ -22,7 +22,7 @@ This is free software, licensed under:
                      Version 1, February 1989
 
  Copyright (C) 1989 Free Software Foundation, Inc.
-                    51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ 51 Franklin St, Suite 500, Boston, MA  02110-1335  USA
 
  Everyone is permitted to copy and distribute verbatim copies
  of this license document, but changing it is not allowed.
@@ -272,7 +272,7 @@ That's all there is to it!
 
 --- The Artistic License 1.0 ---
 
-This software is Copyright (c) 2012 by Yandex LLC.
+This software is Copyright (c) 2015 by Yandex LLC.
 
 This is free software, licensed under:
 
@@ -66,6 +66,7 @@ lib/Ubic/Settings/ConfigFile.pm
 lib/Ubic/SingletonLock.pm
 lib/Ubic/UA.pm
 lib/Ubic/Watchdog.pm
+redhat/perl-Ubic.spec
 root_t/Daemon.pm
 root_t/README
 root_t/credentials.t
@@ -90,12 +91,14 @@ t/bin/explicit-init
 t/bin/locking-daemon
 t/bin/multi-init
 t/cmd.t
+t/credentials.t
 t/daemon.t
 t/loaders/default.t
 t/loaders/ini.t
 t/loaders/json.t
 t/loaders/loader-frontend.t
 t/lock.t
+t/logrotate.t
 t/multiservice/dir.t
 t/multiservice/simple-names.t
 t/multiservice/simple.t
@@ -107,6 +110,7 @@ t/result.t
 t/run.t
 t/service.t
 t/service/README
+t/service/autostart/sleeping-daemon-autostart
 t/service/common/fake-http-service
 t/service/common/fake-http-service2
 t/service/common/multi-impl
@@ -141,4 +145,5 @@ t/simple-daemon.t
 t/ubic-daemon-script.t
 t/ubic-script.t
 t/ubic.t
+t/watchdog-autostart.t
 t/watchdog.t
@@ -4,6 +4,7 @@ author:
   - 'Vyacheslav Matyukhin <mmcleric@yandex-team.ru>'
 build_requires:
   Cwd: 0
+  File::Copy: 0
   File::Find: 0
   Test::Class: 0
   Test::Fatal: 0
@@ -11,7 +12,7 @@ build_requires:
 configure_requires:
   ExtUtils::MakeMaker: 6.30
 dynamic_config: 0
-generated_by: 'Dist::Zilla version 4.300016, CPAN::Meta::Converter version 2.120921'
+generated_by: 'Dist::Zilla version 4.300034, CPAN::Meta::Converter version 2.130880'
 license: perl
 meta-spec:
   url: http://module-build.sourceforge.net/META-spec-v1.4.html
@@ -27,9 +28,12 @@ requires:
   Fcntl: 0
   File::Basename: 0
   File::Path: 0
+  File::Spec: 0
+  File::Which: 0
   Getopt::Long: 2.33
   HTTP::Server::Simple::CGI: 0
   IO::Handle: 0
+  IO::Select: 0
   IO::Socket: 0
   IPC::Open3: 0
   JSON: 0
@@ -51,4 +55,4 @@ resources:
   bugtracker: http://github.com/berekuk/Ubic/issues
   homepage: http://github.com/berekuk/Ubic/wiki
   repository: git://github.com/berekuk/Ubic.git
-version: 1.44
+version: 1.58
@@ -11,24 +11,18 @@ use ExtUtils::MakeMaker 6.30;
 my %WriteMakefileArgs = (
   "ABSTRACT" => "polymorphic service manager",
   "AUTHOR" => "Vyacheslav Matyukhin <mmcleric\@yandex-team.ru>",
-  "BUILD_REQUIRES" => {
-    "Cwd" => 0,
-    "File::Find" => 0,
-    "Test::Class" => 0,
-    "Test::Fatal" => 0,
-    "Test::More" => 0
-  },
+  "BUILD_REQUIRES" => {},
   "CONFIGURE_REQUIRES" => {
     "ExtUtils::MakeMaker" => "6.30"
   },
   "DISTNAME" => "Ubic",
   "EXE_FILES" => [
-    "bin/ubic-periodic",
-    "bin/ubic-watchdog",
     "bin/ubic",
+    "bin/ubic-admin",
     "bin/ubic-daemon",
+    "bin/ubic-periodic",
     "bin/ubic-update",
-    "bin/ubic-admin"
+    "bin/ubic-watchdog"
   ],
   "LICENSE" => "perl",
   "NAME" => "Ubic",
@@ -42,9 +36,12 @@ my %WriteMakefileArgs = (
     "Fcntl" => 0,
     "File::Basename" => 0,
     "File::Path" => 0,
+    "File::Spec" => 0,
+    "File::Which" => 0,
     "Getopt::Long" => "2.33",
     "HTTP::Server::Simple::CGI" => 0,
     "IO::Handle" => 0,
+    "IO::Select" => 0,
     "IO::Socket" => 0,
     "IPC::Open3" => 0,
     "JSON" => 0,
@@ -63,13 +60,34 @@ my %WriteMakefileArgs = (
     "strict" => 0,
     "warnings" => 0
   },
-  "VERSION" => "1.44",
+  "TEST_REQUIRES" => {
+    "Cwd" => 0,
+    "File::Copy" => 0,
+    "File::Find" => 0,
+    "Test::Class" => 0,
+    "Test::Fatal" => 0,
+    "Test::More" => 0
+  },
+  "VERSION" => "1.58",
   "test" => {
     "TESTS" => "t/*.t t/loaders/*.t t/multiservice/*.t"
   }
 );
 
 
+unless ( eval { ExtUtils::MakeMaker->VERSION(6.63_03) } ) {
+  my $tr = delete $WriteMakefileArgs{TEST_REQUIRES};
+  my $br = $WriteMakefileArgs{BUILD_REQUIRES};
+  for my $mod ( keys %$tr ) {
+    if ( exists $br->{$mod} ) {
+      $br->{$mod} = $tr->{$mod} if $tr->{$mod} > $br->{$mod};
+    }
+    else {
+      $br->{$mod} = $tr->{$mod};
+    }
+  }
+}
+
 unless ( eval { ExtUtils::MakeMaker->VERSION(6.56) } ) {
   my $br = delete $WriteMakefileArgs{BUILD_REQUIRES};
   my $pp = $WriteMakefileArgs{PREREQ_PM};
@@ -1,11 +1,11 @@
 
 
 This archive contains the distribution Ubic,
-version 1.44:
+version 1.58:
 
   polymorphic service manager
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
@@ -54,7 +54,10 @@ We also provide .deb packages for Debian/Ubuntu. Latest .deb package can be down
 Debian package build can be reproduced with this command:
     dzil build && cd Ubic* && cp -r ../debian . && debuild
 
-If you'll write ebuilds for Gentoo or specs for RPM-based systems, please contribute them back :)
+Rpm package can be created with this command:
+    rpmbuild -ba redhat/perl-Ubic.spec
+
+If you'll write an ebuild for Gentoo, please contribute it back :)
 
 ## Documentation
 
@@ -93,3 +96,5 @@ But I like Flattr's concept, so why not.
 [![Flattr this git repo](http://api.flattr.com/button/flattr-badge-large.png)](https://flattr.com/submit/auto?user_id=berekuk&url=http://github.com/berekuk/Ubic&title=Ubic&language=en_GB&tags=github&category=software)
 
 You can also +1 Ubic on [MetaCPAN](https://metacpan.org/release/Ubic) if you like it.
+
+[![githalytics.com alpha](https://cruel-carlota.pagodabox.com/799a7f93ca5a43d864a4743b54ff2402 "githalytics.com")](http://githalytics.com/berekuk/Ubic)
@@ -1,7 +1,7 @@
 #!/usr/bin/env perl
 package ubic;
 {
-  $ubic::VERSION = '1.44';
+  $ubic::VERSION = '1.58';
 }
 
 use strict;
@@ -17,13 +17,19 @@ use Ubic;
 use Ubic::Cmd;
 
 return 1 if caller();
+unless (grep { $_ eq '/usr/local/bin' } split /:/, $ENV{PATH}) {
+    $ENV{PATH} = "/usr/local/bin:$ENV{PATH}";
+}
 
 my $force;
 GetOptions(
     'f|force' => \$force,
 ) or pod2usage(2);
 
-unless (@ARGV) {
+if (
+    not @ARGV
+    or @ARGV == 1 and $ARGV[0] eq 'help'
+) {
     pod2usage(2);
 }
 
@@ -43,8 +49,8 @@ else {
     });
 }
 
-
 __END__
+
 =pod
 
 =head1 NAME
@@ -53,7 +59,7 @@ ubic - command-line frontend to ubic services
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 SYNOPSIS
 
@@ -112,10 +118,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,7 +1,7 @@
 #!/usr/bin/env perl
 package ubic_admin;
 {
-  $ubic_admin::VERSION = '1.44';
+  $ubic_admin::VERSION = '1.58';
 }
 
 use strict;
@@ -24,6 +24,7 @@ if (not defined $command or $command ne 'setup') {
 Ubic::Admin::Setup::setup();
 
 __END__
+
 =pod
 
 =head1 NAME
@@ -32,7 +33,7 @@ ubic_admin - ubic administration script
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 SYNOPSIS
 
@@ -119,10 +120,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,7 +1,7 @@
 #!/usr/bin/env perl
 package ubic_daemon;
 {
-  $ubic_daemon::VERSION = '1.44';
+  $ubic_daemon::VERSION = '1.58';
 }
 
 # ABSTRACT: daemonize any binary
@@ -61,8 +61,8 @@ else {
     });
 }
 
-
 __END__
+
 =pod
 
 =head1 NAME
@@ -71,7 +71,7 @@ ubic_daemon - daemonize any binary
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 SYNOPSIS
 
@@ -98,10 +98,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,7 +1,7 @@
 #!/usr/bin/env perl
 package ubic_periodic;
 {
-  $ubic_periodic::VERSION = '1.44';
+  $ubic_periodic::VERSION = '1.58';
 }
 
 # ABSTRACT: run given command every N seconds
@@ -89,6 +89,7 @@ while (1) {
 }
 
 __END__
+
 =pod
 
 =head1 NAME
@@ -97,7 +98,7 @@ ubic_periodic - run given command every N seconds
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 SYNOPSIS
 
@@ -109,10 +110,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,7 +1,7 @@
 #!/usr/bin/env perl
 package ubic_update;
 {
-  $ubic_update::VERSION = '1.44';
+  $ubic_update::VERSION = '1.58';
 }
 
 use strict;
@@ -22,8 +22,8 @@ use Ubic::PortMap;
 
 Ubic::PortMap::update();
 
-
 __END__
+
 =pod
 
 =head1 NAME
@@ -32,7 +32,7 @@ ubic_update - update ubic metadata
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 SYNOPSIS
 
@@ -56,10 +56,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,7 +1,7 @@
 #!/usr/bin/env perl
 package ubic_watchdog;
 {
-  $ubic_watchdog::VERSION = '1.44';
+  $ubic_watchdog::VERSION = '1.58';
 }
 
 use strict;
@@ -16,6 +16,9 @@ use Pod::Usage;
 use Ubic::Watchdog;
 
 return 1 if caller();
+unless (grep { $_ eq '/usr/local/bin' } split /:/, $ENV{PATH}) {
+    $ENV{PATH} .= "/usr/local/bin:$ENV{PATH}";
+}
 
 my $compile_timeout = 10;
 my $verbose;
@@ -32,6 +35,7 @@ Ubic::Watchdog->run(
 );
 
 __END__
+
 =pod
 
 =head1 NAME
@@ -40,7 +44,7 @@ ubic_watchdog - watchdog which checks all ubic services.
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 SYNOPSIS
 
@@ -76,10 +80,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,5 +1,5 @@
 name    = Ubic
-version = 1.44
+version = 1.58
 author  = Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 license = Perl_5
 copyright_holder = Yandex LLC
@@ -1,6 +1,6 @@
 package Ubic::AccessGuard;
 {
-  $Ubic::AccessGuard::VERSION = '1.44';
+  $Ubic::AccessGuard::VERSION = '1.58';
 }
 
 use strict;
@@ -65,6 +65,7 @@ sub DESTROY {
 1;
 
 __END__
+
 =pod
 
 =head1 NAME
@@ -73,7 +74,7 @@ Ubic::AccessGuard - guard for operations with temporarily different effective ui
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 SYNOPSIS
 
@@ -105,7 +106,7 @@ This is considered to be a non-public class. Its interface is subject to change
 
 Construct new access guard object.
 
-User and group will be changed into given C<$credentials>. It will be changed back on guard's desctruction.
+User and group will be changed into given C<$credentials>. It will be changed back on guard's destruction.
 
 =back
 
@@ -115,10 +116,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,6 +1,6 @@
 package Ubic::Admin::Setup;
 {
-  $Ubic::Admin::Setup::VERSION = '1.44';
+  $Ubic::Admin::Setup::VERSION = '1.58';
 }
 
 # ABSTRACT: this module handles ubic setup: asks user some questions and configures your system
@@ -13,6 +13,8 @@ use Getopt::Long 2.33;
 use Carp;
 use IPC::Open3;
 use File::Path;
+use File::Which;
+use File::Spec;
 
 use Ubic::AtomicFile;
 use Ubic::Settings;
@@ -162,6 +164,10 @@ sub setup {
     print_tty "Ubic can be installed either in your home dir or into standard system paths ($defaults{example}).\n";
     print_tty "You need to be root to install it into system.\n";
 
+    unless ($batch_mode) {
+        $batch_mode = prompt_bool("Would you like to configure as much as possible automatically?", 1);
+    }
+
     # ideally, we want is_root option and local option to be orthogonal
     # it's not completely true by now, though
     my $is_root = ( $> ? 0 : 1 );
@@ -198,7 +204,7 @@ sub setup {
     $default_service_dir = $opt_service_dir if defined $opt_service_dir;
     my $service_dir = prompt_str("Service dir?", $default_service_dir);
 
-    print_tty "\nData dir is a directory into which ubic stores all of its data: locks,\n";
+    print_tty "\nData dir is where ubic stores all of its data: locks,\n";
     print_tty "status files, tmp files.\n";
     my $default_data_dir = (
         defined($local_dir)
@@ -208,7 +214,7 @@ sub setup {
     $default_data_dir = $opt_data_dir if defined $opt_data_dir;
     my $data_dir = prompt_str("Data dir?", $default_data_dir);
 
-    print_tty "\nLog dir is a directory into which ubic.watchdog will write its logs.\n";
+    print_tty "\nLog dir is where ubic.watchdog will write its logs.\n";
     print_tty "(Your own services are free to write logs wherever they want.)\n";
     my $default_log_dir = (
         defined($local_dir)
@@ -270,6 +276,43 @@ sub setup {
         $enable_crontab = prompt_bool("Install watchdog's watchdog as a cron job?", $opt_crontab);
     }
 
+    my $crontab_env_fix = '';
+    my $crontab_wrap_bash;
+    my $ubic_watchdog_full_name = which('ubic-watchdog') or die "ubic-watchdog script not found in your current PATH";
+    {
+        my @path = split /:/, $ENV{PATH};
+        my @perls = grep { -x $_ } map { "$_/perl" } @path;
+        if ($perls[0] =~ /perlbrew/) {
+            print_tty "\nYou're using perlbrew.\n";
+
+            my $HOME = $ENV{ORIGINAL_HOME} || $ENV{HOME}; # ORIGINAL_HOME is set in ubic tests
+            unless ($HOME) {
+                die "HOME env variable not defined";
+            }
+            my $perlbrew_config = File::Spec->catfile($ENV{PERLBREW_ROOT} || "$HOME/perl5/perlbrew", "etc/bashrc");
+            if (not -e $perlbrew_config) {
+                die "Can't find perlbrew config (assumed $perlbrew_config)";
+            }
+            print_tty "I'll source your perlbrew config in ubic crontab entry to start the watchdog in the correct environment.\n";
+            $crontab_env_fix .= "source $perlbrew_config && ";
+            $crontab_wrap_bash = 1;
+        }
+        elsif (@perls > 1) {
+            print_tty "\nYou're using custom perl and it's not from perlbrew.\n";
+            print_tty "I'll add your current PATH to ubic crontab entry.\n";
+
+            # TODO - what if PATH contains " quotes? hopefully nobody is that crazy...
+            $crontab_env_fix .= qq[PATH="$ENV{PATH}" ];
+        }
+
+        if ($ENV{PERL5LIB}) {
+            print_tty "\nYou're using custom PERL5LIB.\n";
+            print_tty "I'll add your current PERL5LIB to ubic crontab entry.\n";
+            print_tty "Feel free to edit your crontab manually after installation if necessary.\n";
+            $crontab_env_fix .= qq[PERL5LIB="$ENV{PERL5LIB}" ];
+        }
+    }
+
     my $config_file = (
         defined($local_dir)
         ?  "$local_dir/.ubic.cfg"
@@ -341,18 +384,21 @@ sub setup {
             die "crontab -l failed";
         }
 
-        if ($old_crontab =~ /\subic-watchdog\b/) {
-            print "Looks like you already have ubic commands in your crontab.\n";
-        }
-        else {
-            open my $fh, '|-', 'crontab -' or die "Can't run 'crontab -': $!";
-            my $printc = sub {
-                print {$fh} @_ or die "Can't write to pipe: $!";
-            };
-            $printc->($old_crontab."\n");
-            $printc->("* * * * * ubic-watchdog ubic.watchdog    >>/dev/null 2>>/dev/null\n");
-            close $fh or die "Can't close pipe: $!";
+        my @crontab_lines = split /\n/, $old_crontab;
+        @crontab_lines = grep { $_ !~ /\Qubic-watchdog ubic.watchdog\E/ } @crontab_lines;
+
+        open my $fh, '|-', 'crontab -' or die "Can't run 'crontab -': $!";
+        my $printc = sub {
+            print {$fh} @_ or die "Can't write to pipe: $!";
+        };
+
+        my $crontab_command = "$crontab_env_fix$ubic_watchdog_full_name ubic.watchdog";
+        if ($crontab_wrap_bash) {
+            $crontab_command = "bash -c '$crontab_command'";
         }
+        push @crontab_lines, "* * * * * $crontab_command    >>$log_dir/watchdog.log 2>>$log_dir/watchdog.err.log";
+        $printc->("$_\n") for @crontab_lines;
+        close $fh or die "Can't close pipe: $!";
     }
 
     print "Installing $config_file...\n";
@@ -374,6 +420,7 @@ sub setup {
 1;
 
 __END__
+
 =pod
 
 =head1 NAME
@@ -382,7 +429,7 @@ Ubic::Admin::Setup - this module handles ubic setup: asks user some questions an
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 DESCRPITION
 
@@ -438,10 +485,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,6 +1,6 @@
 package Ubic::AtomicFile;
 {
-  $Ubic::AtomicFile::VERSION = '1.44';
+  $Ubic::AtomicFile::VERSION = '1.58';
 }
 
 use strict;
@@ -41,6 +41,7 @@ sub store($$;$) {
 1;
 
 __END__
+
 =pod
 
 =head1 NAME
@@ -49,7 +50,7 @@ Ubic::AtomicFile - atomic file operations
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 SYNOPSIS
 
@@ -80,10 +81,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,6 +1,6 @@
 package Ubic::Cmd::Results;
 {
-  $Ubic::Cmd::Results::VERSION = '1.44';
+  $Ubic::Cmd::Results::VERSION = '1.58';
 }
 
 use strict;
@@ -94,8 +94,8 @@ sub finish($$) {
 
 1;
 
-
 __END__
+
 =pod
 
 =head1 NAME
@@ -104,7 +104,7 @@ Ubic::Cmd::Results - console results set
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 SYNOPSIS
 
@@ -182,10 +182,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,6 +1,6 @@
 package Ubic::Cmd;
 {
-  $Ubic::Cmd::VERSION = '1.44';
+  $Ubic::Cmd::VERSION = '1.58';
 }
 
 use strict;
@@ -178,7 +178,7 @@ sub do_custom_command {
 sub usage {
     my $self = _obj(shift);
     my $command = shift;
-    print STDERR "Unknown command '$command'\n";
+    print STDERR "Unknown command '$command'. See 'ubic help'.\n";
     exit(2); # or exit(3)? see LSB for details
 }
 
@@ -202,7 +202,7 @@ sub traverse($$$) {
             $indent = $indent + 4;
         }
         for my $subservice ($service->services) {
-            $self->traverse($subservice, $callback, $indent); # FIXME - rememeber result
+            $self->traverse($subservice, $callback, $indent); # FIXME - remember result
         }
     }
     else {
@@ -230,7 +230,7 @@ sub print_status($$;$$) {
         print $name;
 
         # calculating the number of tabs to separate service name from status
-        # status will be aligned whenether possible without sacrificing the real-time properties
+        # status will be aligned whenever possible without sacrificing the real-time properties
         # i.e., we add several tabs to align status with previous lines, but following lines can increase the number of tabs if necessary
         # TODO - there are two possibilities to improve this:
         # 1) look at the further *simple* services and add tabs:
@@ -410,8 +410,8 @@ sub _run_impl {
 
 1;
 
-
 __END__
+
 =pod
 
 =head1 NAME
@@ -420,7 +420,7 @@ Ubic::Cmd - ubic methods with pretty printing.
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 SYNOPSIS
 
@@ -439,7 +439,7 @@ This package mostly conforms to C<Ubic> module API (i.e. to LSB init-script API)
 
 =item B<< new($params) >>
 
-All methods of this class can be invoked as class methods, but you can construct your own instance if neccesary (although constructor doesn't have any options by now, so it is useless).
+All methods of this class can be invoked as class methods, but you can construct your own instance if necessary (although constructor doesn't have any options by now, so it is useless).
 
 =back
 
@@ -525,10 +525,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,6 +1,6 @@
 package Ubic::Credentials::OS::MacOSX;
 {
-  $Ubic::Credentials::OS::MacOSX::VERSION = '1.44';
+  $Ubic::Credentials::OS::MacOSX::VERSION = '1.58';
 }
 
 use strict;
@@ -145,7 +145,7 @@ sub set_effective {
         $) = "$new_gid 0";
         my ($current_gid) = $) =~ /^(\d+)/;
         if ($current_gid != $new_gid) {
-            die "Failed to change group from $group to $current_group: $!";
+            die "Failed to change group from $current_group to $group: $!";
         }
     }
 
@@ -233,6 +233,7 @@ sub set {
 1;
 
 __END__
+
 =pod
 
 =head1 NAME
@@ -241,7 +242,7 @@ Ubic::Credentials::OS::MacOSX - MacOSX-specific credentials implementation
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 METHODS
 
@@ -287,10 +288,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,6 +1,6 @@
 package Ubic::Credentials::OS::POSIX;
 {
-  $Ubic::Credentials::OS::POSIX::VERSION = '1.44';
+  $Ubic::Credentials::OS::POSIX::VERSION = '1.58';
 }
 
 use strict;
@@ -178,7 +178,7 @@ sub set_effective {
         $) = "$new_gid 0";
         my ($current_gid) = $) =~ /^(\d+)/;
         if ($current_gid != $new_gid) {
-            die "Failed to change group from $group to $current_group: $!";
+            die "Failed to change group from $current_group to $group: $!";
         }
     }
 
@@ -228,8 +228,8 @@ sub eq {
     if (
         $self->effective_user_id == $other->effective_user_id
         and $self->real_user_id == $other->real_user_id
-        and $self->_groups_equal($self->effective_group_id, $other->effective_group_id)
-        and $self->_groups_equal($self->real_group_id, $other->real_group_id)
+        and $self->_groups_equal(join(" ", $self->effective_group_id), join(" ", $other->effective_group_id))
+        and $self->_groups_equal(join(" ", $self->real_group_id), join(" ", $other->real_group_id))
     ) {
         return 1;
     }
@@ -273,6 +273,7 @@ sub as_string {
 1;
 
 __END__
+
 =pod
 
 =head1 NAME
@@ -281,7 +282,7 @@ Ubic::Credentials::OS::POSIX - POSIX-specific credentials implementation
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 METHODS
 
@@ -325,10 +326,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,6 +1,6 @@
 package Ubic::Credentials::OS::Windows;
 {
-  $Ubic::Credentials::OS::Windows::VERSION = '1.44';
+  $Ubic::Credentials::OS::Windows::VERSION = '1.58';
 }
 
 use strict;
@@ -24,6 +24,7 @@ sub set {}
 1;
 
 __END__
+
 =pod
 
 =head1 NAME
@@ -32,7 +33,7 @@ Ubic::Credentials::OS::Windows - dummy credentials module
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 DESCRIPTION
 
@@ -48,10 +49,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,6 +1,6 @@
 package Ubic::Credentials;
 {
-  $Ubic::Credentials::VERSION = '1.44';
+  $Ubic::Credentials::VERSION = '1.58';
 }
 
 use strict;
@@ -60,6 +60,7 @@ sub as_string {
 1;
 
 __END__
+
 =pod
 
 =head1 NAME
@@ -68,7 +69,7 @@ Ubic::Credentials - base class for OS-specific credential methods
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 SYNOPSIS
 
@@ -126,10 +127,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,6 +1,6 @@
 package Ubic::Daemon::OS::Linux;
 {
-  $Ubic::Daemon::OS::Linux::VERSION = '1.44';
+  $Ubic::Daemon::OS::Linux::VERSION = '1.58';
 }
 
 use strict;
@@ -79,6 +79,7 @@ sub pid_exists {
 1;
 
 __END__
+
 =pod
 
 =head1 NAME
@@ -87,7 +88,7 @@ Ubic::Daemon::OS::Linux - linux-specific daemonize helpers
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 DESCRIPTION
 
@@ -102,10 +103,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,6 +1,6 @@
 package Ubic::Daemon::OS::POSIX;
 {
-  $Ubic::Daemon::OS::POSIX::VERSION = '1.44';
+  $Ubic::Daemon::OS::POSIX::VERSION = '1.58';
 }
 
 use strict;
@@ -24,7 +24,8 @@ sub pid2guid {
 sub pid2cmd {
     my ($self, $pid) = validate_pos(@_, 1, { type => SCALAR, regex => qr/^\d+$/ });
 
-    my $result = qx(ps -p $pid -o pid,command 2>/dev/null);
+    # see POSIX specification - http://pubs.opengroup.org/onlinepubs/009696799/utilities/ps.html
+    my $result = qx(ps -p $pid -o pid,comm 2>/dev/null);
     $result =~ s/^.*\n//; # drop first line
     my ($ps_pid, $ps_command) = $result =~ /^\s*(\d+)\s+(.*)$/;
     unless ($ps_pid) {
@@ -59,6 +60,7 @@ sub pid_exists {
 1;
 
 __END__
+
 =pod
 
 =head1 NAME
@@ -67,7 +69,7 @@ Ubic::Daemon::OS::POSIX - POSIX-compatible daemonize helpers
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 AUTHOR
 
@@ -75,10 +77,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,6 +1,6 @@
 package Ubic::Daemon::OS;
 {
-  $Ubic::Daemon::OS::VERSION = '1.44';
+  $Ubic::Daemon::OS::VERSION = '1.58';
 }
 
 use strict;
@@ -32,6 +32,7 @@ sub pid_exists {
 1;
 
 __END__
+
 =pod
 
 =head1 NAME
@@ -40,7 +41,7 @@ Ubic::Daemon::OS - base class for os-specific daemon methods
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 METHODS
 
@@ -78,10 +79,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,6 +1,6 @@
 package Ubic::Daemon::PidState;
 {
-  $Ubic::Daemon::PidState::VERSION = '1.44';
+  $Ubic::Daemon::PidState::VERSION = '1.58';
 }
 
 use strict;
@@ -154,6 +154,7 @@ sub write {
 1;
 
 __END__
+
 =pod
 
 =head1 NAME
@@ -162,7 +163,7 @@ Ubic::Daemon::PidState - internal object representing process info stored on dis
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 INTERFACE SUPPORT
 
@@ -182,7 +183,7 @@ Check if pid dir doesn't exist yet.
 
 =item B<init()>
 
-Create pid dir. After tihs method is called, C<is_empty()> will start to return false value.
+Create pid dir. After this method is called, C<is_empty()> will start to return false value.
 
 =item B<read()>
 
@@ -213,10 +214,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,6 +1,6 @@
 package Ubic::Daemon::Status;
 {
-  $Ubic::Daemon::Status::VERSION = '1.44';
+  $Ubic::Daemon::Status::VERSION = '1.58';
 }
 
 use strict;
@@ -15,6 +15,7 @@ sub new {
     my $class = shift;
     my $params = validate(@_, {
         pid => 1,
+        guardian_pid => 1,
     });
     return bless $params => $class;
 }
@@ -25,10 +26,17 @@ sub pid {
     return $self->{pid};
 }
 
+sub guardian_pid {
+    my $self = shift;
+    validate_pos(@_);
+    return $self->{guardian_pid};
+}
+
 
 1;
 
 __END__
+
 =pod
 
 =head1 NAME
@@ -37,11 +45,12 @@ Ubic::Daemon::Status - daemon status structure
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 SYNOPSIS
 
     say $status->pid;
+    say $status->guardian_pid;
 
 =head1 METHODS
 
@@ -55,6 +64,10 @@ Constructor. Should be called from L<Ubic::Daemon> only.
 
 Get daemon's PID.
 
+=item B<< guardian_pid() >>
+
+Get guardian's PID.
+
 =back
 
 =head1 SEE ALSO
@@ -67,10 +80,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,6 +1,6 @@
 package Ubic::Daemon;
 {
-  $Ubic::Daemon::VERSION = '1.44';
+  $Ubic::Daemon::VERSION = '1.58';
 }
 
 use strict;
@@ -10,6 +10,7 @@ use warnings;
 
 
 use IO::Handle;
+use IO::Select;
 use POSIX qw(setsid :sys_wait_h);
 use Time::HiRes qw(sleep);
 use Params::Validate qw(:all);
@@ -142,11 +143,12 @@ sub start_daemon($) {
         term_timeout => { type => SCALAR, default => 10, regex => qr/^\d+$/ },
         cwd => { type => SCALAR, optional => 1 },
         env => { type => HASHREF, optional => 1 },
+        proxy_logs => { type => SCALAR, optional => 1 },
         credentials => { isa => 'Ubic::Credentials', optional => 1 },
         start_hook => { type => CODEREF, optional => 1 },
     });
-    my           ($bin, $function, $name, $pidfile, $stdout, $stderr, $ubic_log, $term_timeout, $cwd, $env, $credentials, $start_hook)
-    = @options{qw/ bin   function   name   pidfile   stdout   stderr   ubic_log   term_timeout   cwd   env   credentials   start_hook /};
+    my           ($bin, $function, $name, $pidfile, $stdout, $stderr, $ubic_log, $term_timeout, $cwd, $env, $credentials, $start_hook, $proxy_logs)
+    = @options{qw/ bin   function   name   pidfile   stdout   stderr   ubic_log   term_timeout   cwd   env   credentials   start_hook   proxy_logs /};
     if (not defined $bin and not defined $function) {
         croak "One of 'bin' and 'function' should be specified";
     }
@@ -169,8 +171,6 @@ sub start_daemon($) {
     my $pid_state = Ubic::Daemon::PidState->new($pidfile);
     $pid_state->init;
 
-    my $stdin = '/dev/null';
-
     pipe my ($read_pipe, $write_pipe) or die "pipe failed";
     my $child;
 
@@ -204,17 +204,22 @@ sub start_daemon($) {
                 $OS->close_all_fh($write_pipe_fd_num); # except pipe
             }
 
-            {
+            my $open_handles_sub = sub {
                 my $guard;
                 $guard = Ubic::AccessGuard->new($credentials) if $credentials;
                 open STDOUT, ">>", $stdout or die "Can't write to '$stdout': $!";
                 open STDERR, ">>", $stderr or die "Can't write to '$stderr': $!";
-            }
+                STDOUT->autoflush(1);
+                STDERR->autoflush(1);
+                if (defined $ubic_log) {
+                    open $ubic_fh, ">>", $ubic_log or die "Can't write to '$ubic_log': $!";
+                    $ubic_fh->autoflush(1);
+                }
+            };
+            $open_handles_sub->();
+            my $stdin = '/dev/null';
             open STDIN, "<", $stdin or die "Can't read from '$stdin': $!";
-            if (defined $ubic_log) {
-                open $ubic_fh, ">>", $ubic_log or die "Can't write to '$ubic_log': $!";
-                $ubic_fh->autoflush(1);
-            }
+
             $SIG{HUP} = 'ignore';
             $0 = "ubic-guardian $name";
             setsid; # ubic-daemon gets it's own session
@@ -231,6 +236,13 @@ sub start_daemon($) {
             $pid_state->remove;
             _log($ubic_fh, "got lock");
 
+            my %daemon_pipes;
+            if (defined $proxy_logs) {
+                for my $handle (qw/stdout stderr/) {
+                    pipe my ($read, $write) or die "pipe for daemon $handle failed";
+                    $daemon_pipes{$handle} = {read => $read, write => $write};
+                }
+            }
             my $child;
             if ($child = fork) {
                 # guardian
@@ -282,6 +294,48 @@ sub start_daemon($) {
                 close $write_pipe or die "Can't close pipe: $!";
                 undef $write_pipe;
 
+                if (defined $proxy_logs) {
+                    $SIG{HUP} = sub {
+                        eval { $open_handles_sub->() };
+                        if ($@) {
+                            _log($ubic_fh, "failed to reopen stdout/stderr handles: $@");
+                            $kill_sub->();
+                        }
+                        else {
+                            _log($ubic_fh, "reopened stdout/stderr");
+                        }
+                    };
+
+                    for my $handle (qw/stdout stderr/) {
+                        close($daemon_pipes{$handle}{write}) or do {
+                            _log($ubic_fh, "Can't close $handle write: $!");
+                            die "Can't close $handle write: $!" 
+                        };
+                    }
+                    my $sel = IO::Select->new();
+                    $sel->add($daemon_pipes{stdout}{read}, $daemon_pipes{stderr}{read});
+                    my $BUFF_SIZE = 4096;
+                    READ:
+                    while ($OS->pid_exists($child)) { # this loop is needed because of timeout in can_read
+                        while (my @ready = $sel->can_read(1)) {
+                            my $exhausted = 0;
+                            for my $handle (@ready) {
+                                my $data;
+                                my $bytes_read = sysread($handle, $data, $BUFF_SIZE);
+                                die "Can't poll $handle: $!" unless defined $bytes_read; # handle EWOULDBLOCK?
+                                $exhausted += 1 if $bytes_read == 0;
+                                if (fileno $handle == fileno $daemon_pipes{stdout}{read}) {
+                                    print STDOUT $data;
+                                }
+                                if (fileno $handle == fileno $daemon_pipes{stderr}{read}) {
+                                    print STDERR $data;
+                                }
+                            }
+                            last READ if $exhausted == @ready;
+                        }
+                    }
+                }
+
                 $? = 0;
                 waitpid($child, 0);
                 my $code = $?;
@@ -321,6 +375,13 @@ sub start_daemon($) {
                 close($write_pipe) or die "Can't close pipe: $!";
                 undef $write_pipe;
 
+                if (defined $proxy_logs) {
+                    # redirecting standard streams to pipes
+                    close($daemon_pipes{$_}{read}) or die "Can't close $_ read: $!" for qw/stdout stderr/;
+                    open STDOUT, '>&=', $daemon_pipes{stdout}{write} or die "Can't open stdout write: $!";
+                    open STDERR, '>&=', $daemon_pipes{stderr}{write} or die "Can't open stderr write: $!";
+                }
+
                 # finally, run underlying binary
                 if (ref $bin) {
                     exec(@$bin) or die "exec failed: $!";
@@ -371,7 +432,7 @@ sub check_daemon {
     my $piddata = $pid_state->read;
     unless ($lock) {
         # locked => daemon is alive
-        return Ubic::Daemon::Status->new({ pid => $piddata->{daemon} });
+        return Ubic::Daemon::Status->new({ pid => $piddata->{daemon}, guardian_pid => $piddata->{pid} });
     }
 
     unless ($piddata) {
@@ -419,6 +480,7 @@ sub check_daemon {
 1;
 
 __END__
+
 =pod
 
 =head1 NAME
@@ -427,7 +489,7 @@ Ubic::Daemon - daemon management utilities
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 SYNOPSIS
 
@@ -529,6 +591,20 @@ Change working directory before starting a daemon. Optional.
 
 Modify environment before starting a daemon. Optional. Must be a plain hashref if specified.
 
+=item I<proxy_logs>
+
+Boolean flag.
+
+If enabled, C<ubic-guardian> will replace daemon's stdout and stderr filehandles with pipes, proxy all data to the log files, and reopen them on I<SIGHUP>.
+
+There're two reasons why this is not the default:
+
+1) It's a bit slower than allowing the daemon to write its logs itself;
+
+2) The code is new and more complex than the simple "spawn the daemon and wait for it to finish".
+
+On the other hand, using this feature allows you to reopen all logs without restarting the service.
+
 =item I<credentials>
 
 Set given credentials before execing into a daemon. Optional, must be an C<Ubic::Credentials> object.
@@ -543,9 +619,9 @@ Note that hook is called *before* the credentials are set. Raising the ulimits w
 
 =item I<term_timeout>
 
-Can contain integer number of seconds to wait between sending I<SIGTERM> and I<SIGKILL> to daemon.
+Number of seconds to wait between sending I<SIGTERM> and I<SIGKILL> to the daemon on stopping.
 
-Zero value means that guardian will send sigkill to daemon immediately.
+Zero value means that guardian will send I<SIGKILL> to the daemon immediately.
 
 Default is 10 seconds.
 
@@ -581,10 +657,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,6 +1,6 @@
 package Ubic::Lockf::Alarm;
 {
-  $Ubic::Lockf::Alarm::VERSION = '1.44';
+  $Ubic::Lockf::Alarm::VERSION = '1.58';
 }
 
 use strict;
@@ -29,6 +29,7 @@ sub DESTROY ($) {
 1;
 
 __END__
+
 =pod
 
 =head1 NAME
@@ -37,7 +38,7 @@ Ubic::Lockf::Alarm - alarm guard
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 DESCRIPTION
 
@@ -59,10 +60,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,6 +1,6 @@
 package Ubic::Lockf;
 {
-  $Ubic::Lockf::VERSION = '1.44';
+  $Ubic::Lockf::VERSION = '1.58';
 }
 
 use strict;
@@ -118,8 +118,8 @@ sub dissolve {
 
 1;
 
-
 __END__
+
 =pod
 
 =head1 NAME
@@ -128,7 +128,7 @@ Ubic::Lockf - file locker with an automatic out-of-scope unlocking mechanism
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 SYNOPSIS
 
@@ -139,7 +139,7 @@ version 1.44
 
 =head1 DESCRIPTION
 
-C<lockf> is a perlfunc C<flock> wrapper. The lock is autotamically released as soon as the assotiated object is
+C<lockf> is a perlfunc C<flock> wrapper. The lock is autotamically released as soon as the associated object is
 no longer referenced.
 
 =head1 METHODS
@@ -164,7 +164,7 @@ OFF by default. Tells to achieve a shared lock. If not set, an exclusive lock is
 
 ON by default. If unset, a non-blocking mode of flock is used. If this flock fails because the lock is already held by some other process,
 C<undef> is returned. If the failure reason is somewhat different, permissions problems or the
-absence of a target file directory for example, an exception is raisen.
+absence of a target file directory for example, an exception is raised.
 
 =item I<timeout>
 
@@ -194,10 +194,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,6 +1,6 @@
 package Ubic::Logger;
 {
-  $Ubic::Logger::VERSION = '1.44';
+  $Ubic::Logger::VERSION = '1.58';
 }
 
 use strict;
@@ -32,8 +32,8 @@ sub ERROR {
 
 1;
 
-
 __END__
+
 =pod
 
 =head1 NAME
@@ -42,7 +42,7 @@ Ubic::Logger - very simple logging functions
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 SYNOPSIS
 
@@ -72,10 +72,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,8 +1,8 @@
 package Ubic::Manual::FAQ;
 # ABSTRACT: frequently asked questions about Ubic
 
-
 __END__
+
 =pod
 
 =head1 NAME
@@ -11,7 +11,7 @@ Ubic::Manual::FAQ - frequently asked questions about Ubic
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 QUESTIONS
 
@@ -27,7 +27,7 @@ In the future, this one-liner will be reimplemented as "ubic fix-permissions" co
 
 Yes you can, but you have to be careful.
 
-Perlbrew depends on environment variables, so you have to make sure that they are configured correctly in all cases when you call ubic. This especially includes the crontab which entry ubic installs for you. You'll probably have to edit it manually, like this:
+Perlbrew depends on environment variables, so you have to make sure that they are configured correctly in all cases when you call ubic. This especially includes the crontab entry which ubic installs for you. You'll probably have to edit it manually, like this:
 
   * * * * * . /home/your_login/perl5/perlbrew/etc/bashrc && ubic-watchdog ubic.watchdog    >>/dev/null 2>>/dev/null
 
@@ -105,23 +105,25 @@ In other words, if you don't use C<ubic.ping>, you can stop both C<ubic.update>
 
 =head2 Why is it called "ubic", anyway?
 
-It's called after "Ubik" - science fiction novel by Philip K. Dick. I spelled it incorrectly in early releases, because "c" and "k" are indistinguishable in Russian language, and now it's too late to fix this stupid typo (and I'll be very thankful to anyone who'll invent appropriate backronym).
+It's called after "Ubik" - science fiction novel by Philip K. Dick. I spelled it incorrectly in early releases, because "c" and "k" are indistinguishable in Russian language, and now it's too late to fix this.
 
 Why is it called after "Ubik"? Well, these two quotes can hint to some suggestions:
 
   "This substance, whose name is derived from the word "ubiquity", has the property of preserving people who are in half-life."
   "Ubik is a metaphor for God. Ubik is all-powerful and all-knowing, and Ubik is everywhere."
 
+Alternatively, one possible backronym is "Ubic Because I Can" :)
+(Thanks to Christopher Paulicka for suggesting it!)
+
 =head1 AUTHOR
 
 Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -2,8 +2,8 @@ package Ubic::Manual::Intro;
 
 # ABSTRACT: Initial introduction
 
-
 __END__
+
 =pod
 
 =head1 NAME
@@ -12,7 +12,7 @@ Ubic::Manual::Intro - Initial introduction
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 DESCRIPTION
 
@@ -101,10 +101,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -2,8 +2,8 @@ package Ubic::Manual::Multiservices;
 
 # ABSTRACT: Multiservices - dynamic generation of service tree
 
-
 __END__
+
 =pod
 
 =head1 NAME
@@ -12,7 +12,7 @@ Ubic::Manual::Multiservices - Multiservices - dynamic generation of service tree
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 DESCRIPTION
 
@@ -125,10 +125,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -2,8 +2,8 @@ package Ubic::Manual::Overview;
 
 # ABSTRACT: General ubic concepts and architecture
 
-
 __END__
+
 =pod
 
 =head1 NAME
@@ -12,7 +12,7 @@ Ubic::Manual::Overview - General ubic concepts and architecture
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 DESCRIPTION
 
@@ -89,10 +89,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,6 +1,6 @@
 package Ubic::Multiservice::Dir;
 {
-  $Ubic::Multiservice::Dir::VERSION = '1.44';
+  $Ubic::Multiservice::Dir::VERSION = '1.58';
 }
 
 use strict;
@@ -142,6 +142,7 @@ sub multiop {
 1;
 
 __END__
+
 =pod
 
 =head1 NAME
@@ -150,7 +151,7 @@ Ubic::Multiservice::Dir - multiservice which uses directory with configs to inst
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 METHODS
 
@@ -174,10 +175,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,6 +1,6 @@
 package Ubic::Multiservice::Simple;
 {
-  $Ubic::Multiservice::Simple::VERSION = '1.44';
+  $Ubic::Multiservice::Simple::VERSION = '1.58';
 }
 
 use strict;
@@ -51,8 +51,8 @@ sub multiop {
 
 1;
 
-
 __END__
+
 =pod
 
 =head1 NAME
@@ -61,7 +61,7 @@ Ubic::Multiservice::Simple - simplest multiservice, configured in constructor
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 SYNOPSIS
 
@@ -90,10 +90,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,6 +1,6 @@
 package Ubic::Multiservice;
 {
-  $Ubic::Multiservice::VERSION = '1.44';
+  $Ubic::Multiservice::VERSION = '1.58';
 }
 # ABSTRACT: interface of multiservice representing several named services
 
@@ -107,8 +107,8 @@ sub multiop($) {
 
 1;
 
-
 __END__
+
 =pod
 
 =head1 NAME
@@ -117,7 +117,7 @@ Ubic::Multiservice - interface of multiservice representing several named servic
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 SYNOPSIS
 
@@ -225,10 +225,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,6 +1,6 @@
 package Ubic::Persistent;
 {
-  $Ubic::Persistent::VERSION = '1.44';
+  $Ubic::Persistent::VERSION = '1.58';
 }
 
 use strict;
@@ -78,6 +78,7 @@ sub DESTROY {
 1;
 
 __END__
+
 =pod
 
 =head1 NAME
@@ -86,7 +87,7 @@ Ubic::Persistent - simple hash-to-file persistence object
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 SYNOPSIS
 
@@ -123,10 +124,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,6 +1,6 @@
 package Ubic::Ping::Service;
 {
-  $Ubic::Ping::Service::VERSION = '1.44';
+  $Ubic::Ping::Service::VERSION = '1.58';
 }
 
 # ABSTRACT: ubic.ping service
@@ -47,7 +47,7 @@ sub new {
                 return 'not running';
             }
             my $ua = Ubic::UA->new(timeout => 1);
-            my $response = $ua->get("http://localhost:$port/ping");
+            my $response = $ua->get("http://127.0.0.1:$port/ping");
             if ($response->{error}) {
                 return result('broken', $response->{error});
             }
@@ -67,6 +67,7 @@ sub new {
 1;
 
 __END__
+
 =pod
 
 =head1 NAME
@@ -75,7 +76,7 @@ Ubic::Ping::Service - ubic.ping service
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 INTERFACE SUPPORT
 
@@ -97,10 +98,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,7 +1,7 @@
 #!/usr/bin/perl
 package Ubic::Ping;
 {
-  $Ubic::Ping::VERSION = '1.44';
+  $Ubic::Ping::VERSION = '1.58';
 }
 
 use strict;
@@ -21,33 +21,36 @@ sub _print_status($;$) {
 
     unless (Ubic->is_enabled($name)) {
         if ($options->{noc}) {
-            print "HTTP/1.0 500 Disabled\r\n\r\n";
+            print "HTTP/1.1 500 Disabled\r\n";
         }
         else {
-            print "HTTP/1.0 200 OK\r\n\r\n";
+            print "HTTP/1.1 200 OK\r\n";
         }
+        print "Content-Type: text/plain; charset=utf-8\r\n\r\n";
         print "disabled\n";
         return;
     }
     my $status = Ubic->cached_status($name)->status; # should read status from static file on disk
     if ($status eq 'running') {
-        print "HTTP/1.0 200 OK\r\n\r\n";
+        print "HTTP/1.1 200 OK\r\n";
+        print "Content-Type: text/plain; charset=utf-8\r\n\r\n";
         print "ok\n";
         return;
     }
     else {
         if ($options->{noc}) {
             if ($status =~ /^[\w ]+$/) {
-                print "HTTP/1.0 500 $status\r\n\r\n";
+                print "HTTP/1.1 500 $status\r\n";
             }
             else {
                 # invalid status, fallback to default status message
-                print "HTTP/1.0 500 Wrong status\r\n\r\n";
+                print "HTTP/1.1 500 Wrong status\r\n";
             }
         }
         else {
-            print "HTTP/1.0 200 OK\r\n\r\n";
+            print "HTTP/1.1 200 OK\r\n";
         }
+        print "Content-Type: text/plain; charset=utf-8\r\n\r\n";
         print "$status\n";
         return;
     }
@@ -59,7 +62,8 @@ sub handle_request {
     try {
         if ($cgi->path_info eq '/ping') {
             # ping self
-            print "HTTP/1.0 200 OK\r\n\r\n";
+            print "HTTP/1.1 200 OK\r\n";
+            print "Content-Type: text/plain; charset=utf-8\r\n\r\n";
             print "ok\n";
             return;
         }
@@ -67,7 +71,8 @@ sub handle_request {
             my $port = $1;
             my $name = Ubic::PortMap::port2name($port);
             unless (defined $name) {
-                print "HTTP/1.0 404 Not found\r\n\r\n";
+                print "HTTP/1.1 404 Not found\r\n";
+                print "Content-Type: text/plain; charset=utf-8\r\n\r\n";
                 print "Service at port '$port' not found\n";
                 return;
             }
@@ -78,7 +83,8 @@ sub handle_request {
             my $port = $1;
             my $name = Ubic::PortMap::port2name($port);
             unless (defined $name) {
-                print "HTTP/1.0 404 Not found\r\n\r\n";
+                print "HTTP/1.1 404 Not found\r\n";
+                print "Content-Type: text/plain; charset=utf-8\r\n\r\n";
                 print "Service at port '$port' not found\n";
                 return;
             }
@@ -87,20 +93,23 @@ sub handle_request {
         }
         elsif (my ($name) = $cgi->path_info =~ m{^/status/service/(.+?)/?$}) {
             unless (Ubic->has_service($name)) {
-                print "HTTP/1.0 404 Not found\r\n\r\n";
+                print "HTTP/1.1 404 Not found\r\n";
+                print "Content-Type: text/plain; charset=utf-8\r\n\r\n";
                 print "Service with name '$name' not found\n";
                 return;
             }
             _print_status($name);
         }
         else {
-            print "HTTP/1.0 404 Not found\r\n\r\n";
+            print "HTTP/1.1 404 Not found\r\n";
+            print "Content-Type: text/plain; charset=utf-8\r\n\r\n";
             print "Expected /status/service/NAME or /status/port/PORT query\n";
             return;
         }
     }
     catch {
-        print "HTTP/1.0 500 Internal error\r\n\r\n";
+        print "HTTP/1.1 500 Internal error\r\n";
+        print "Content-Type: text/plain; charset=utf-8\r\n\r\n";
         print "Error: $_";
     };
 }
@@ -108,6 +117,7 @@ sub handle_request {
 1;
 
 __END__
+
 =pod
 
 =head1 NAME
@@ -116,7 +126,7 @@ Ubic::Ping - http server which returns service status by it's name or port
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 AUTHOR
 
@@ -124,10 +134,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,6 +1,6 @@
 package Ubic::PortMap;
 {
-  $Ubic::PortMap::VERSION = '1.44';
+  $Ubic::PortMap::VERSION = '1.58';
 }
 
 use strict;
@@ -76,8 +76,8 @@ sub port2name($) {
 
 1;
 
-
 __END__
+
 =pod
 
 =head1 NAME
@@ -86,7 +86,7 @@ Ubic::PortMap - update and read mapping of ports to service names.
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 SYNOPSIS
 
@@ -121,10 +121,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,6 +1,6 @@
 package Ubic::Result::Class;
 {
-  $Ubic::Result::Class::VERSION = '1.44';
+  $Ubic::Result::Class::VERSION = '1.58';
 }
 
 use strict;
@@ -41,12 +41,15 @@ sub status {
     if (grep { $_ eq $self->{type} } ('running', 'already running', 'started', 'already started', 'restarted', 'reloaded', 'stopping')) {
         return 'running';
     }
-    elsif (grep { $_ eq $self->{type} } ('not running', 'stopped', 'down', 'starting')) {
+    elsif (grep { $_ eq $self->{type} } ('not running', 'stopped', 'starting')) {
         return 'not running';
     }
     elsif (grep { $_ eq $self->{type} } ('down')) {
         return 'down';
     }
+    elsif (grep { $_ eq $self->{type} } ('autostarting')) {
+        return 'autostarting';
+    }
     else {
         return 'broken';
     }
@@ -81,6 +84,7 @@ sub as_string {
 1;
 
 __END__
+
 =pod
 
 =head1 NAME
@@ -89,7 +93,7 @@ Ubic::Result::Class - ubic result object
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 SYNOPSIS
 
@@ -125,6 +129,8 @@ Possible statuses:
 
 =item I<down>
 
+=item I<autostarting>
+
 =back
 
 =head1 ACTIONS
@@ -177,10 +183,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,6 +1,6 @@
 package Ubic::Result;
 {
-  $Ubic::Result::VERSION = '1.44';
+  $Ubic::Result::VERSION = '1.58';
 }
 
 use strict;
@@ -31,8 +31,8 @@ sub result {
 
 1;
 
-
 __END__
+
 =pod
 
 =head1 NAME
@@ -41,7 +41,7 @@ Ubic::Result - common return value for many ubic interfaces
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 SYNOPSIS
 
@@ -114,10 +114,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,6 +1,6 @@
 package Ubic::Run;
 {
-  $Ubic::Run::VERSION = '1.44';
+  $Ubic::Run::VERSION = '1.58';
 }
 
 use strict;
@@ -55,6 +55,7 @@ sub import {
 1;
 
 __END__
+
 =pod
 
 =head1 NAME
@@ -63,7 +64,7 @@ Ubic::Run - really simple way to write init scripts
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 SYNOPSIS
 
@@ -100,10 +101,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,6 +1,6 @@
 package Ubic::Service::Common;
 {
-  $Ubic::Service::Common::VERSION = '1.44';
+  $Ubic::Service::Common::VERSION = '1.58';
 }
 
 use strict;
@@ -21,7 +21,7 @@ sub new {
         start       => { type => CODEREF },
         stop        => { type => CODEREF },
         status      => { type => CODEREF },
-        name        => { type => SCALAR, regex => qr/^[\w-]+$/, optional => 1 }, # violates Ubic::Service incapsulation...
+        name        => { type => SCALAR, regex => qr/^[\w-]+$/, optional => 1 }, # violates Ubic::Service encapsulation...
         port        => { type => SCALAR, regex => qr/^\d+$/, optional => 1 },
         custom_commands => { type => HASHREF, default => {} },
         user        => { type => SCALAR, optional => 1 },
@@ -93,6 +93,7 @@ sub do_custom_command {
 1;
 
 __END__
+
 =pod
 
 =head1 NAME
@@ -101,7 +102,7 @@ Ubic::Service::Common - common way to construct new service by specifying severa
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 SYNOPSIS
 
@@ -182,10 +183,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,6 +1,6 @@
 package Ubic::Service::SimpleDaemon;
 {
-  $Ubic::Service::SimpleDaemon::VERSION = '1.44';
+  $Ubic::Service::SimpleDaemon::VERSION = '1.58';
 }
 
 use strict;
@@ -32,6 +32,23 @@ sub _pid_dir {
     return $PID_DIR;
 }
 
+sub _send_signal {
+    my ($self, $signal) = @_;
+
+    my $daemon = check_daemon($self->pidfile);
+    unless ($daemon) {
+        return result('not running');
+    }
+
+    my $pid = $daemon->pid;
+    kill $signal => $pid;
+
+    my $guardian_pid = $daemon->guardian_pid;
+    kill HUP => $guardian_pid;
+
+    return result('reloaded', "sent $self->{reload_signal} to $pid, sent HUP to $guardian_pid");
+}
+
 sub new {
     my $class = shift;
     my $params = validate(@_, {
@@ -47,7 +64,10 @@ sub new {
         cwd => { type => SCALAR, optional => 1 },
         env => { type => HASHREF, optional => 1 },
         reload_signal => { type => SCALAR, optional => 1 },
+        term_timeout => { type => SCALAR, optional => 1, regex => qr/^\d+$/ },
+        stop_timeout => { type => SCALAR, optional => 1, regex => qr/^\d+$/ },
         ulimit => { type => HASHREF, optional => 1 },
+        auto_start => { type => BOOLEAN, default => 0 },
     });
 
     if ($params->{ulimit}) {
@@ -56,6 +76,10 @@ sub new {
         if ($@) {
             die "BSD::Resource is not installed";
         }
+        if (BSD::Resource->VERSION < 1.29) {
+            # 1.29 supports string names for resources
+            die "BSD::Resource >= 1.29 required";
+        }
     }
 
     return bless {%$params} => $class;
@@ -74,9 +98,12 @@ sub start_impl {
         pidfile => $self->pidfile,
         bin => $self->{bin},
     };
-    for (qw/ env cwd stdout stderr ubic_log /) {
+    for (qw/ env cwd stdout stderr ubic_log term_timeout /) {
         $start_params->{$_} = $self->{$_} if defined $self->{$_};
     }
+    if ($self->{reload_signal}) {
+        $start_params->{proxy_logs} = 1;
+    }
     if (defined $self->{daemon_user}) {
         $start_params->{credentials} = Ubic::Credentials->new(
             user => $self->{daemon_user},
@@ -113,7 +140,9 @@ sub group {
 
 sub stop_impl {
     my ($self) = @_;
-    stop_daemon($self->pidfile);
+    my $options = {};
+    $options->{timeout} = $self->{stop_timeout} if $self->{stop_timeout};
+    stop_daemon($self->pidfile,$options);
 }
 
 sub status_impl {
@@ -131,23 +160,39 @@ sub reload {
     unless (defined $self->{reload_signal}) {
         return result('unknown', 'not implemented');
     }
-    my $daemon = check_daemon($self->pidfile);
-    unless ($daemon) {
-        return result('not running');
-    }
+    return $self->_send_signal($self->{reload_signal});
+}
 
-    my $pid = $daemon->pid;
-    # TODO - should we send signal to guardian instead?
-    # reload doesn't reopen ubic_log/stdout/stderr by now.
-    kill $self->{reload_signal} => $pid;
+sub auto_start {
+    my $self = shift;
+    return $self->{auto_start};
+}
 
-    return result('reloaded', "sent $self->{reload_signal} to $pid");
+
+our %SIGNALS = (
+    sigusr1 => 'SIGUSR1',
+    sigusr2 => 'SIGUSR2',
+);
+
+sub custom_commands {
+    my ($self) = @_;
+    return keys %SIGNALS;
+}
+
+sub do_custom_command {
+    my ($self, $command) = @_;
+    unless (defined $SIGNALS{$command}) {
+        return result('unknown', 'not implemented');
+    }
+
+    return $self->_send_signal($SIGNALS{$command});
 }
 
 
 1;
 
 __END__
+
 =pod
 
 =head1 NAME
@@ -156,7 +201,7 @@ Ubic::Service::SimpleDaemon - service module for daemonizing any binary
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 SYNOPSIS
 
@@ -199,7 +244,7 @@ This is the only mandatory parameter, everything else is optional.
 
 User under which the service will operate.
 
-Default user depends on the configuration chosen at C<ubic-admin setup> stage. See L<Ubic::Settings> for more defails.
+Default user depends on the configuration chosen at C<ubic-admin setup> stage. See L<Ubic::Settings> for more details.
 
 =item I<group>
 
@@ -245,13 +290,27 @@ If your service's I<user> is C<root> and I<daemon_user> is something else, you c
 
 L<BSD::Resource> must be installed to use this feature.
 
+=item I<term_timeout>
+
+Number of seconds to wait between sending I<SIGTERM> and I<SIGKILL> to the daemon on stopping.
+
+Zero value means that guardian will send I<SIGKILL> to the daemon immediately.
+
+Default is 10 seconds.
+
+=item I<stop_timeout>
+
+Number of seconds to wait before raising exception that daemon can't be stopped.
+
+This should always be greater than I<term_timeout>, and defaults to 30 seconds (via L<Ubic::Daemon>'s defaults.)
+
 =item I<reload_signal>
 
 Send given signal to the daemon on C<reload> command.
 
 Can take either integer value or signal name (i.e., I<HUP>).
 
-Note that this signal won't reopen I<stdout>, I<stderr> or I<ubic_log> logs. Sorry.
+The signal will be sent both to the daemon, and to the guardian process. Guardian process will have I<proxy_logs> feature enabled, so it'll reopen I<stdout>, I<stderr> and I<ubic_log> as well.
 
 =item I<daemon_user>
 
@@ -259,7 +318,7 @@ Note that this signal won't reopen I<stdout>, I<stderr> or I<ubic_log> logs. Sor
 
 Change credentials to the given user and group before execing into daemon.
 
-The difference between these options and I<user>/I<group> options is that for I<daemon_*> options, credentials will be set just before before starting the actual daemon. All other service operations will be done using default user. Refer to L<Ubic::Manual::Overview/"Permissions and security"> for the further explanations.
+The difference between these options and I<user>/I<group> options is that for I<daemon_*> options, credentials will be set just before starting the actual daemon. All other service operations will be done using default user. Refer to L<Ubic::Manual::Overview/"Permissions and security"> for the further explanations.
 
 =item I<name>
 
@@ -267,6 +326,10 @@ Service's name.
 
 Name will usually be set by upper-level multiservice. Don't set it unless you know what you're doing.
 
+=item I<auto_start>
+
+Autostart flag is off by default. See L<Ubic::Service> C<auto_start> method for details.
+
 =back
 
 =item B<< pidfile() >>
@@ -275,6 +338,11 @@ Get pid filename. It will be concatenated from simple-daemon pid dir and service
 
 =back
 
+=head1 CUSTOM COMMANDS
+
+All services using this class support two custom commands: I<sigusr1> and I<sigusr2>.
+So, C<ubic sigusr1 your.service.name> will send I<SIGUSR1> to your daemon (and also send I<SIGHUP> to ubic-guardian, which can result in reopening log files.)
+
 =head1 SEE ALSO
 
 L<Ubic::Daemon> - module for daemonizing any binary.
@@ -285,10 +353,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,6 +1,6 @@
 package Ubic::Service::Skeleton;
 {
-  $Ubic::Service::Skeleton::VERSION = '1.44';
+  $Ubic::Service::Skeleton::VERSION = '1.58';
 }
 
 use strict;
@@ -138,8 +138,8 @@ sub _do_stop {
 
 1;
 
-
 __END__
+
 =pod
 
 =head1 NAME
@@ -148,7 +148,7 @@ Ubic::Service::Skeleton - skeleton of any service with common start/stop logic
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 ACTIONS
 
@@ -184,7 +184,7 @@ Subclass must overload following methods with simple status, start and stop impl
 
 =item B<status_impl>
 
-Status implentation. Should return result object or plain string which coerces to result object.
+Status implementation. Should return result object or plain string which coerces to result object.
 
 =item B<start_impl>
 
@@ -226,10 +226,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,6 +1,6 @@
 package Ubic::Service::Utils;
 {
-  $Ubic::Service::Utils::VERSION = '1.44';
+  $Ubic::Service::Utils::VERSION = '1.58';
 }
 
 use strict;
@@ -51,8 +51,8 @@ sub wait_for_status {
 
 1;
 
-
 __END__
+
 =pod
 
 =head1 NAME
@@ -61,7 +61,7 @@ Ubic::Service::Utils - helpers for custom service authors
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 FUNCTIONS
 
@@ -105,10 +105,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,6 +1,6 @@
 package Ubic::Service;
 {
-  $Ubic::Service::VERSION = '1.44';
+  $Ubic::Service::VERSION = '1.58';
 }
 
 use strict;
@@ -93,10 +93,15 @@ sub parent_name($;$) {
     }
 }
 
+sub auto_start($) {
+    return 0;
+}
+
 
 1;
 
 __END__
+
 =pod
 
 =head1 NAME
@@ -105,7 +110,7 @@ Ubic::Service - interface and the base class for any ubic service
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 SYNOPSIS
 
@@ -210,17 +215,17 @@ Services can define custom commands which don't fit into the usual C<start/stop/
 
 =item B<custom_commands()>
 
-Get the list of service's custom commands, if there are any.
+Should return the list of service's custom commands, if there are any.
 
 =item B<do_custom_command($command)>
 
-Execute specified command, if it is supported. Throw an exception otherwise.
+Should execute specified command, if it is supported. Throw an exception otherwise.
 
 =back
 
 =head2 NAME METHODS
 
-These methods should not be overriden by specific service classes.
+These methods should not be overridden by specific service classes.
 They are usually used by the code which loads service (i.e. some kind of L<Ubic::Multiservice>) to associate service with its name.
 
 These methods are just the simple interdependent r/w accessors.
@@ -255,6 +260,12 @@ Get or set a name of the service's parent.
 
 Service's loader (i.e. some kind of L<Ubic::Multiservice>) is responsible for calling this method immediately after a service is constructed, like this: C<< $service->parent_name($self->full_name) >> (check out L<Ubic::Multiservice> sources for more).
 
+=item B<auto_start()>
+
+A boolean value that determines the state of a service if it has never been explicitly enabled or disabled yet. Service is considered initially enabled when auto_start is true.
+
+Default is false, so initial service status is I<off>, and you have to run C<ubic start service_name> to start it.
+
 =back
 
 =head1 FUTURE DIRECTIONS
@@ -278,10 +289,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,6 +1,6 @@
 package Ubic::ServiceLoader::Base;
 {
-  $Ubic::ServiceLoader::Base::VERSION = '1.44';
+  $Ubic::ServiceLoader::Base::VERSION = '1.58';
 }
 
 # ABSTRACT: abstract base class for service loaders
@@ -20,6 +20,7 @@ sub load {
 1;
 
 __END__
+
 =pod
 
 =head1 NAME
@@ -28,7 +29,7 @@ Ubic::ServiceLoader::Base - abstract base class for service loaders
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 DESCRIPTION
 
@@ -54,10 +55,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,6 +1,6 @@
 package Ubic::ServiceLoader::Default;
 {
-  $Ubic::ServiceLoader::Default::VERSION = '1.44';
+  $Ubic::ServiceLoader::Default::VERSION = '1.58';
 }
 
 # ABSTRACT: default service loader
@@ -45,6 +45,7 @@ sub load {
 1;
 
 __END__
+
 =pod
 
 =head1 NAME
@@ -53,7 +54,7 @@ Ubic::ServiceLoader::Default - default service loader
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 SYNOPSIS
 
@@ -67,10 +68,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,6 +1,6 @@
 package Ubic::ServiceLoader::Ext::ini;
 {
-  $Ubic::ServiceLoader::Ext::ini::VERSION = '1.44';
+  $Ubic::ServiceLoader::Ext::ini::VERSION = '1.58';
 }
 
 # ABSTRACT: loader for ini-style configs
@@ -52,6 +52,7 @@ sub load {
 1;
 
 __END__
+
 =pod
 
 =head1 NAME
@@ -60,7 +61,7 @@ Ubic::ServiceLoader::Ext::ini - loader for ini-style configs
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 SYNOPSIS
 
@@ -77,10 +78,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,6 +1,6 @@
 package Ubic::ServiceLoader::Ext::json;
 {
-  $Ubic::ServiceLoader::Ext::json::VERSION = '1.44';
+  $Ubic::ServiceLoader::Ext::json::VERSION = '1.58';
 }
 
 # ABSTRACT: loader for json-style configs
@@ -60,6 +60,7 @@ sub load {
 1;
 
 __END__
+
 =pod
 
 =head1 NAME
@@ -68,7 +69,7 @@ Ubic::ServiceLoader::Ext::json - loader for json-style configs
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 SYNOPSIS
 
@@ -88,10 +89,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,6 +1,6 @@
 package Ubic::ServiceLoader;
 {
-  $Ubic::ServiceLoader::VERSION = '1.44';
+  $Ubic::ServiceLoader::VERSION = '1.58';
 }
 
 # ABSTRACT: load service from file
@@ -61,6 +61,7 @@ sub load {
 1;
 
 __END__
+
 =pod
 
 =head1 NAME
@@ -69,7 +70,7 @@ Ubic::ServiceLoader - load service from file
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 SYNOPSIS
 
@@ -118,10 +119,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,6 +1,6 @@
 package Ubic::Settings::ConfigFile;
 {
-  $Ubic::Settings::ConfigFile::VERSION = '1.44';
+  $Ubic::Settings::ConfigFile::VERSION = '1.58';
 }
 
 use strict;
@@ -36,7 +36,7 @@ sub write {
 
     my $content = "";
 
-    for my $key (keys %$config) {
+    for my $key (sort keys %$config) {
         my $value = $config->{$key};
         if ($value =~ /\n/) {
             die "Invalid config line  '$key = $value', values can't contain line breaks";
@@ -57,6 +57,7 @@ sub write {
 1;
 
 __END__
+
 =pod
 
 =head1 NAME
@@ -65,7 +66,7 @@ Ubic::Settings::ConfigFile - single ubic config file
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 SYNOPSIS
 
@@ -105,10 +106,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,6 +1,6 @@
 package Ubic::Settings;
 {
-  $Ubic::Settings::VERSION = '1.44';
+  $Ubic::Settings::VERSION = '1.58';
 }
 
 use strict;
@@ -99,6 +99,7 @@ sub check_settings {
 1;
 
 __END__
+
 =pod
 
 =head1 NAME
@@ -107,7 +108,7 @@ Ubic::Settings - ubic settings
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 SYNOPSIS
 
@@ -185,10 +186,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,6 +1,6 @@
 package Ubic::SingletonLock;
 {
-  $Ubic::SingletonLock::VERSION = '1.44';
+  $Ubic::SingletonLock::VERSION = '1.58';
 }
 
 use strict;
@@ -40,6 +40,7 @@ sub DESTROY {
 1;
 
 __END__
+
 =pod
 
 =head1 NAME
@@ -48,7 +49,7 @@ Ubic::SingletonLock - lock which can be safely created several times from the sa
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 SYNOPSIS
 
@@ -89,10 +90,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,6 +1,6 @@
 package Ubic::UA;
 {
-  $Ubic::UA::VERSION = '1.44';
+  $Ubic::UA::VERSION = '1.58';
 }
 
 # ABSTRACT: tiny http client
@@ -68,6 +68,7 @@ sub get {
 1;
 
 __END__
+
 =pod
 
 =head1 NAME
@@ -76,11 +77,11 @@ Ubic::UA - tiny http client
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 DESCRIPTION
 
-This module is a tiny and horribly incomplete http useragent implementetion.
+This module is a tiny and horribly incomplete http useragent implementation.
 
 It's used by L<Ubic::Ping::Service> and it allows ubic to avoid dependency on LWP.
 
@@ -110,10 +111,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,6 +1,6 @@
 package Ubic::Watchdog;
 {
-  $Ubic::Watchdog::VERSION = '1.44';
+  $Ubic::Watchdog::VERSION = '1.58';
 }
 
 use strict;
@@ -137,12 +137,19 @@ sub check($) {
             return;
         }
 
+        my $cached_status = Ubic->cached_status($name);
         my $status = Ubic->status($name);
         unless ($status->status eq 'running') {
             # following code can throw an exception, so we want to cache invalid status immediately
             Ubic->set_cached_status($name, $status);
 
-            ERROR("$name status is '$status', restarting");
+            if ($cached_status eq "autostarting") {
+                INFO("$name is autostarting");
+            }
+            else {
+                ERROR("$name status is '$status', restarting");
+            }
+
             Ubic->restart($name);
 
             # This is a precaution against services with wrong start/status logic.
@@ -166,6 +173,7 @@ sub check($) {
 1;
 
 __END__
+
 =pod
 
 =head1 NAME
@@ -174,7 +182,7 @@ Ubic::Watchdog - watchdog code
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 SYNOPSIS
 
@@ -251,10 +259,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -1,6 +1,6 @@
 package Ubic;
 {
-  $Ubic::VERSION = '1.44';
+  $Ubic::VERSION = '1.58';
 }
 
 use strict;
@@ -185,7 +185,9 @@ sub is_enabled($$) {
     my ($name) = validate_pos(@_, $validate_service);
 
     die "Service '$name' not found" unless $self->root_service->has_service($name);
-    return unless -e $self->status_file($name);
+    unless (-e $self->status_file($name)) {
+        return $self->service($name)->auto_start();
+    }
 
     my $status_obj = $self->status_obj_ro($name);
     if ($status_obj->{enabled} or not exists $status_obj->{enabled}) {
@@ -212,11 +214,13 @@ sub cached_status($$) {
     my ($name) = validate_pos(@_, $validate_service);
 
     my $type;
-    unless ($self->is_enabled($name)) {
+    if (not $self->is_enabled($name)) {
         $type = 'disabled';
     }
-    else {
+    elsif (-e $self->status_file($name)) {
         $type = $self->status_obj_ro($name)->{status};
+    } else {
+        $type = 'autostarting';
     }
     return Ubic::Result::Class->new({ type => $type, cached => 1 });
 }
@@ -316,7 +320,7 @@ sub set_cached_status($$$) {
     }
     my $lock = $self->lock($name);
 
-    if ($self->status_obj_ro($name)->{status} eq $status) {
+    if (-e $self->status_file($name) and $self->status_obj_ro($name)->{status} eq $status) {
         # optimization - don't update status if nothing changed
         return;
     }
@@ -474,7 +478,7 @@ sub forked_call {
             POSIX::_exit(0); # don't allow to lock to be released - this process was forked from unknown environment, don't want to run unknown destructors
         }
         catch {
-            # probably tmp_file is not writtable
+            # probably tmp_file is not writable
             warn $_;
             POSIX::_exit(1);
         };
@@ -500,6 +504,7 @@ sub forked_call {
 1;
 
 __END__
+
 =pod
 
 =head1 NAME
@@ -508,7 +513,7 @@ Ubic - polymorphic service manager
 
 =head1 VERSION
 
-version 1.44
+version 1.58
 
 =head1 SYNOPSIS
 
@@ -782,13 +787,19 @@ Christian Walde <walde.christian@googlemail.com>
 
 Ivan Bessarabov <ivan@bessarabov.ru>
 
+Oleg Komarov <komarov@cpan.org>
+
+Andrew Kirkpatrick <ubermonk@gmail.com>
+
 =head1 SEE ALSO
 
 Most Ubic-related links are collected on github wiki: L<http://github.com/berekuk/Ubic/wiki>.
 
-L<Daemon::Control> lets you write init scripts in perl.
+L<Daemon::Control> and L<Proc::Launcher> provide the start/stop/status style mechanisms for init scripts and apachectl-style commands.
 
-L<ControlFreak>, L<Server::Control> and L<Proc::Launcher> are similar to Ubic in being "apachectl-style" managers.
+L<Server::Control> is an apachectl-style, heavyweight subclassable module for handling network daemons.
+
+L<ControlFreak> - process supervisor, similar to Ubic in its command-line interface.
 
 There are also L<App::Daemon>, L<App::Control> and L<Supervisor>.
 
@@ -804,10 +815,9 @@ Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is copyright (c) 2012 by Yandex LLC.
+This software is copyright (c) 2015 by Yandex LLC.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
 
 =cut
-
@@ -0,0 +1,76 @@
+Name:           perl-Ubic
+Version:        1.48
+Release:        1%{?dist}
+Summary:        Polymorphic service manager
+License:        GPL+ or Artistic
+Group:          Development/Libraries
+URL:            http://search.cpan.org/dist/Ubic/
+Source0:        http://www.cpan.org/authors/id/M/MM/MMCLERIC/Ubic-%{version}.tar.gz
+BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
+BuildArch:      noarch
+BuildRequires:  perl(Class::Accessor::Fast)
+BuildRequires:  perl(Config)
+BuildRequires:  perl(Config::Tiny)
+BuildRequires:  perl(ExtUtils::MakeMaker)
+BuildRequires:  perl(File::Which)
+BuildRequires:  perl(HTTP::Server::Simple::CGI)
+BuildRequires:  perl(JSON)
+BuildRequires:  perl(List::MoreUtils)
+BuildRequires:  perl(Params::Validate)
+BuildRequires:  perl(parent)
+BuildRequires:  perl(Test::Class)
+BuildRequires:  perl(Test::Fatal)
+BuildRequires:  perl(Test::More)
+BuildRequires:  perl(Time::HiRes)
+BuildRequires:  perl(Try::Tiny)
+Requires:       perl(Class::Accessor::Fast)
+Requires:       perl(Config)
+Requires:       perl(Config::Tiny)
+Requires:       perl(File::Which)
+Requires:       perl(HTTP::Server::Simple::CGI)
+Requires:       perl(JSON)
+Requires:       perl(List::MoreUtils)
+Requires:       perl(Params::Validate)
+Requires:       perl(parent)
+Requires:       perl(Time::HiRes)
+Requires:       perl(Try::Tiny)
+Requires:       perl(:MODULE_COMPAT_%(eval "`%{__perl} -V:version`"; echo $version))
+
+%description
+This module is a perl frontend to ubic services.
+
+%prep
+%setup -q -n Ubic-%{version}
+
+%build
+%{__perl} Makefile.PL INSTALLDIRS=vendor
+make %{?_smp_mflags}
+
+%install
+rm -rf $RPM_BUILD_ROOT
+
+make pure_install PERL_INSTALL_ROOT=$RPM_BUILD_ROOT
+
+find $RPM_BUILD_ROOT -type f -name .packlist -exec rm -f {} \;
+find $RPM_BUILD_ROOT -depth -type d -exec rmdir {} 2>/dev/null \;
+
+%{_fixperms} $RPM_BUILD_ROOT/*
+
+%check
+make test
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%files
+%defattr(-,root,root,-)
+%doc Changes dist.ini LICENSE README README.md root_t
+%{perl_vendorlib}/*
+%{_bindir}/ubic
+%{_bindir}/ubic-*
+%{_mandir}/man1/*
+%{_mandir}/man3/*
+
+%changelog
+* Thu Feb 14 2013 Duncan Hutty <dhutty@allgoodbits.org> 1.48-1
+- Specfile autogenerated by cpanspec 1.78 with minor modifications
@@ -35,6 +35,6 @@ sub file2uid {
 is(file2uid('tfiles/pid'), scalar(getpwnam('root')), 'pidfile belongs to root');
 is(file2uid('tfiles/stdout'), scalar(getpwnam('daemon')), 'stdout belongs to daemon');
 is(file2uid('tfiles/stderr'), scalar(getpwnam('daemon')), 'stderr belongs to daemon');
-is(file2uid('tfiles/ubic.log'), scalar(getpwnam('root')), 'stderr belongs to root');
+is(file2uid('tfiles/ubic.log'), scalar(getpwnam('daemon')), 'stderr belongs to daemon');
 
 stop_daemon('tfiles/pid');
@@ -49,7 +49,7 @@ sub test_grants :Tests {
         is($stat[5], scalar(getgrnam($group)), "$file group is $group") unless $^O eq 'darwin';
     };
     $check_file->("tfiles/$name.result", $result_user, $result_group);
-    $check_file->("tfiles/$name.ubic.log", $user, $group);
+    $check_file->("tfiles/$name.ubic.log", $result_user, $result_group);
     $check_file->("tfiles/ubic/status/$name", $user, $group);
     $check_file->("tfiles/ubic/lock/$name", $user, $group);
 }
@@ -6,7 +6,7 @@ use warnings;
 use Test::More;
 use Test::Fatal;
 
-if ($^O =~ /MSWin|cygwin|solaris/i) {
+if ($^O =~ /MSWin|cygwin/i) {
     BAIL_OUT("OS unsupported");
 }
 
@@ -62,30 +62,30 @@ my $ua = LWP::UserAgent->new;
 
 # ping ping (2)
 {
-    my $response = $ua->get("http://localhost:$port/ping");
+    my $response = $ua->get("http://127.0.0.1:$port/ping");
     ok($response->is_success, '/ping successful');
     is($response->content, "ok\n", '/ping returns ok');
 }
 
 # /status/service/ (9)
 {
-    my $response = $ua->get("http://localhost:$port/status/service/unknown");
+    my $response = $ua->get("http://127.0.0.1:$port/status/service/unknown");
     is($response->code, 404, 'unknown service not found');
 
-    $response = $ua->get("http://localhost:$port/status/service/ubic.ping");
+    $response = $ua->get("http://127.0.0.1:$port/status/service/ubic.ping");
     is($response->code, 200, 'ubic.ping service found');
     is($response->content, "ok\n", 'ubic.ping service is ok');
 
-    $response = $ua->get("http://localhost:$port/status/service/fake-http-service");
+    $response = $ua->get("http://127.0.0.1:$port/status/service/fake-http-service");
     is($response->code, 200, "service fake-http-service found");
     is($response->content, "disabled\n", 'fake-http-service is not running');
 
     Ubic->start('fake-http-service');
-    $response = $ua->get("http://localhost:$port/status/service/fake-http-service");
+    $response = $ua->get("http://127.0.0.1:$port/status/service/fake-http-service");
     is($response->code, 200, "service fake-http-service found");
     is($response->content, "ok\n", 'fake-http-service now is running');
 
-    $response = $ua->get("http://localhost:$port/status/service/fake-http-service2");
+    $response = $ua->get("http://127.0.0.1:$port/status/service/fake-http-service2");
     is($response->code, 200, "service fake-http-service2 found");
     is($response->content, "disabled\n", 'fake-http-service is still down');
     Ubic->stop('fake-http-service');
@@ -93,25 +93,25 @@ my $ua = LWP::UserAgent->new;
 
 # /status/port/ (9)
 {
-    my $response = $ua->get("http://localhost:$port/status/port/80");
+    my $response = $ua->get("http://127.0.0.1:$port/status/port/80");
     is($response->code, 404, 'service on 80 port not found');
 
-    $response = $ua->get("http://localhost:$port/status/port/$port");
+    $response = $ua->get("http://127.0.0.1:$port/status/port/$port");
     is($response->code, 200, "service on $port port found");
     is($response->content, "ok\n", 'ubic.ping service is running');
 
-    $response = $ua->get("http://localhost:$port/status/port/$another_port");
+    $response = $ua->get("http://127.0.0.1:$port/status/port/$another_port");
     is($response->code, 200, "service on $another_port port found");
     is($response->content, "disabled\n", 'service is not running');
 
     Ubic->start('fake-http-service');
-    $response = $ua->get("http://localhost:$port/status/port/$another_port");
+    $response = $ua->get("http://127.0.0.1:$port/status/port/$another_port");
     is($response->code, 200, "service on $another_port found");
     is($response->content, "ok\n", "service on $another_port now is running");
 
     Ubic->stop('fake-http-service');
     Ubic->start('fake-http-service2');
-    $response = $ua->get("http://localhost:$port/status/port/$another_port");
+    $response = $ua->get("http://127.0.0.1:$port/status/port/$another_port");
     is($response->code, 200, "service on $another_port found");
     is($response->content, "ok\n", "service on $another_port is still running - ubic.ping chooses best service by port");
 
@@ -120,13 +120,13 @@ my $ua = LWP::UserAgent->new;
 
 # /noc/ (4)
 {
-    my $response = $ua->get("http://localhost:$port/noc/80");
+    my $response = $ua->get("http://127.0.0.1:$port/noc/80");
     is($response->code, 404, 'service on 80 port not found');
 
-    $response = $ua->get("http://localhost:$port/noc/$port");
+    $response = $ua->get("http://127.0.0.1:$port/noc/$port");
     is($response->code, 200, "service on $port port found");
     is($response->content, "ok\n", 'ubic.ping service is running');
 
-    $response = $ua->get("http://localhost:$port/noc/$another_port");
+    $response = $ua->get("http://127.0.0.1:$port/noc/$another_port");
     is($response->code, 500, "service on $port port is down");
 }
@@ -0,0 +1,13 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use lib 'lib';
+use Test::More;
+
+use Ubic::Credentials;
+
+ok(Ubic::Credentials->new->eq(Ubic::Credentials->new));
+
+done_testing;
@@ -0,0 +1,51 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use parent qw(Test::Class);
+use Test::More;
+use Test::Fatal;
+
+use lib 'lib';
+
+use File::Copy qw(move);
+use IO::Handle;
+use Time::HiRes qw(sleep);
+
+use t::Utils;
+
+use Ubic;
+use Ubic::Service::SimpleDaemon;
+
+sub setup :Test(setup) {
+    rebuild_tfiles;
+    local_ubic;
+}
+
+sub logrotate :Tests(4) {
+    my $service = Ubic::Service::SimpleDaemon->new({
+        name => 'simple1',
+        bin => ['perl', '-e', 'use IO::Handle; use Time::HiRes qw(sleep); STDOUT->autoflush(1); $SIG{HUP} = "IGNORE"; for (1..100) {print "stdout: $_\n"; warn "stderr $_\n"; sleep 0.1;}'],
+        stdout => 'tfiles/stdout',
+        stderr => 'tfiles/stderr',
+        ubic_log => 'tfiles/ubic.log',
+        reload_signal => 'HUP',
+    });
+    $service->start;
+    sleep 1;
+    move 'tfiles/stdout', 'tfiles/stdout2';
+    move 'tfiles/stderr', 'tfiles/stderr2';
+    move 'tfiles/ubic.log', 'tfiles/ubic.log.2';
+    sleep 1;
+    $service->reload;
+    sleep 2;
+    $service->stop;
+    ok((-s 'tfiles/stdout' and -s 'tfiles/stdout2'), 'stdout was reopened');
+    ok((-s 'tfiles/stderr' and -s 'tfiles/stderr2'), 'stderr was reopened');
+    ok((-s 'tfiles/ubic.log' and -s 'tfiles/ubic.log.2'), 'ubic_log was reopened');
+
+    like(slurp('tfiles/ubic.log'), qr{reopened stdout/stderr}, 'log line about stdout/stderr being reopened');
+}
+
+__PACKAGE__->new->runtests;
@@ -0,0 +1,7 @@
+# vim:ft=perl
+use Ubic::Service::SimpleDaemon;
+
+Ubic::Service::SimpleDaemon->new({
+    bin => 'sleep 100',
+    auto_start => 1,
+});
@@ -13,7 +13,9 @@ rebuild_tfiles();
 use Config;
 my $perl = $Config{perlpath};
 
+local $ENV{ORIGINAL_HOME} = $ENV{HOME};
 local $ENV{HOME} = 'tfiles';
+local $ENV{PATH} = "bin:$ENV{PATH}";
 
 xsystem("$perl ./bin/ubic-admin setup --batch-mode --no-install-services --no-crontab --local --reconfigure");
 
@@ -23,6 +25,6 @@ ok(-d 'tfiles/ubic/service', 'ubic service dir created');
 ok(-e 'tfiles/.ubic.cfg', 'ubic config created');
 
 my @config = split /\n/, slurp 'tfiles/.ubic.cfg';
-like($config[0], qr{^default_user = \S+$}, 'default user config line');
-like($config[1], qr{^service_dir = .*tfiles/ubic/service$}, 'services dir config line');
-like($config[2], qr{^data_dir = .*tfiles/ubic/data$}, 'services dir config line');
+like($config[0], qr{^data_dir = .*tfiles/ubic/data$}, 'services dir config line');
+like($config[1], qr{^default_user = \S+$}, 'default user config line');
+like($config[2], qr{^service_dir = .*tfiles/ubic/service$}, 'services dir config line');
@@ -126,11 +126,11 @@ sub reload :Tests(6) {
 
     $service->start;
 
-    sleep 1; # let the code load and set sighub handler
+    sleep 1; # let the code load and set sighup handler
 
     $result = $service->reload;
     is($result->action, 'reloaded', 'reload successful');
-    like($result->msg, qr/^sent HUP to \d+$/, 'reload result message');
+    like($result->msg, qr/^sent HUP to \d+, sent HUP to \d+$/, 'reload result message');
 
     sleep 1; # wait while code handles the first exception
 
@@ -149,6 +149,9 @@ sub ulimit :Tests(4) {
     if ($@) {
         return 'BSD::Resource is not installed, skip ulimit tests';
     }
+    if (BSD::Resource->VERSION < 1.29) {
+        return "BSD::Resource is too old to work with Ubic, but it's an optional dependency, so we'll just skip ulimit tests";
+    }
     my $service = Ubic::Service::SimpleDaemon->new({
         name => 'limited_service',
         bin => ['perl', '-e', 'system(q{bash -c "ulimit -n"}); sleep 5'],
@@ -179,7 +182,57 @@ sub ulimit :Tests(4) {
         },
     });
     my $exception = exception { $invalid_service->start };
-    like $exception, qr/Failed to create daemon: 'Error: setrlimit: Unknown limit 'BLAH'/, 'start with invalid ulimit fails';
+    like $exception, qr/Failed to create daemon: '.*Error: setrlimit: Unknown limit 'BLAH'/s, 'start with invalid ulimit fails';
+}
+
+sub term_timeout_default :Tests {
+    my $service = Ubic::Service::SimpleDaemon->new({
+        name => 'undying',
+        bin => ['perl', '-e', 'use IO::Handle; $SIG{TERM} = sub { print "ignore sigterm\n"; STDOUT->flush; }; print "stdout\n"; STDOUT->flush; sleep 100 for 1..10'],
+        stdout => 'tfiles/stdout',
+        stderr => 'tfiles/stderr',
+        ubic_log => 'tfiles/ubic.log',
+    });
+
+    my $time = time;
+
+    $service->start;
+    like($service->status, qr/^running \(pid \d+\)$/, 'start works');
+
+    sleep 1;
+
+    $service->stop;
+    is($service->status, 'not running', 'stop works');
+
+    is(slurp('tfiles/stdout'), "stdout\nignore sigterm\n", 'daemon stdout');
+
+    cmp_ok(time - $time, '>=', 10, 'stop took more than 10 seconds');
+}
+
+sub term_timeout_custom :Tests {
+    my $service = Ubic::Service::SimpleDaemon->new({
+        name => 'undying',
+        bin => ['perl', '-e', 'use IO::Handle; $SIG{TERM} = sub { print "ignore sigterm\n"; STDOUT->flush; }; print "stdout\n"; STDOUT->flush; sleep 100 for 1..10'],
+        stdout => 'tfiles/stdout',
+        stderr => 'tfiles/stderr',
+        ubic_log => 'tfiles/ubic.log',
+        term_timeout => 3,
+    });
+
+    my $time = time;
+
+    $service->start;
+    like($service->status, qr/^running \(pid \d+\)$/, 'start works');
+
+    sleep 1;
+
+    $service->stop;
+    is($service->status, 'not running', 'stop works');
+
+    is(slurp('tfiles/stdout'), "stdout\nignore sigterm\n", 'daemon stdout');
+
+    cmp_ok(time - $time, '>=', 3, 'stop took more than 3 seconds');
+    cmp_ok(time - $time, '<=', 5, 'stop took less than 5 seconds');
 }
 
 __PACKAGE__->new->runtests;
@@ -21,7 +21,7 @@ sub setup :Test(setup) {
 
 sub unknown_command :Test(1) {
     system("$perl bin/ubic blah >>tfiles/log 2>>tfiles/err.log");
-    is(slurp('tfiles/err.log'), "Unknown command 'blah'\n", 'unknown command error');
+    is(slurp('tfiles/err.log'), "Unknown command 'blah'. See 'ubic help'.\n", 'unknown command error');
 }
 
 sub force :Test(8) {
@@ -0,0 +1,38 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use parent qw(Test::Class);
+use Test::More;
+
+use lib 'lib';
+
+use Config;
+my $perl = $Config{perlpath};
+$perl = "$perl -Mt::Utils::IgnoreWarn";
+
+use Ubic;
+use Ubic::Watchdog;
+use t::Utils;
+
+my $ignore_warn = ignore_warn(qr/Can't construct 'broken': failed/);
+
+sub setup :Test(setup) {
+    rebuild_tfiles;
+    local_ubic(service_dirs => ['t/service/autostart']);
+}
+
+sub enable_disable :Test(2) {
+    ok(Ubic->is_enabled('sleeping-daemon-autostart'), 'autostart service is initially enabled');
+    Ubic->disable('sleeping-daemon-autostart');
+    ok(not(Ubic->is_enabled('sleeping-daemon-autostart')), 'sleeping-daemon-autostart is explicitely disabled');
+}
+
+sub autostart :Test(2) {
+    is(Ubic->cached_status('sleeping-daemon-autostart')->status, "autostarting");
+    xsystem("$perl bin/ubic-watchdog >>tfiles/watchdog.log 2>>tfiles/watchdog.err.log");
+    is(Ubic->service('sleeping-daemon-autostart')->status->status, "running");
+}
+
+__PACKAGE__->new->runtests;
@@ -107,8 +107,11 @@ sub compile_timeout :Test(3) {
 
     my $time = time;
     system("$perl bin/ubic-watchdog --compile-timeout=2 >>tfiles/watchdog.log 2>>tfiles/watchdog.err.log");
-    ok(time - $time < 4, 'ubic-watchdog compile-timeout happened');
-    ok(time - $time >= 2, 'ubic-watchdog compile-timeout happened');
+
+    # 3-4 seconds is usually enough, 7 seconds is a precaution against slow systems
+    ok(time - $time <= 7, 'ubic-watchdog compile-timeout happened early');
+    ok(time - $time >= 2, 'ubic-watchdog compile-timeout happened after 2 seconds');
+
     like(slurp('tfiles/watchdog.err.log'), qr/Couldn't compile Ubic::Multiservice::Dir.* services in 2 seconds/);
 }