Add 'nix daemon' command

This commit is contained in:
Eelco Dolstra 2021-01-14 00:05:04 +01:00
parent 28ef6ebf91
commit 7a472a76d4
5 changed files with 98 additions and 44 deletions

View file

@ -13,6 +13,8 @@ namespace nix {
extern std::string programPath; extern std::string programPath;
extern char * * savedArgv;
class EvalState; class EvalState;
struct Pos; struct Pos;
class Store; class Store;

View file

@ -1,3 +1,4 @@
#include "command.hh"
#include "shared.hh" #include "shared.hh"
#include "local-store.hh" #include "local-store.hh"
#include "remote-store.hh" #include "remote-store.hh"
@ -150,7 +151,7 @@ static ref<Store> openUncachedStore()
} }
static void daemonLoop(char * * argv) static void daemonLoop()
{ {
if (chdir("/") == -1) if (chdir("/") == -1)
throw SysError("cannot change current directory"); throw SysError("cannot change current directory");
@ -232,9 +233,9 @@ static void daemonLoop(char * * argv)
setSigChldAction(false); setSigChldAction(false);
// For debugging, stuff the pid into argv[1]. // For debugging, stuff the pid into argv[1].
if (peer.pidKnown && argv[1]) { if (peer.pidKnown && savedArgv[1]) {
string processName = std::to_string(peer.pid); string processName = std::to_string(peer.pid);
strncpy(argv[1], processName.c_str(), strlen(argv[1])); strncpy(savedArgv[1], processName.c_str(), strlen(savedArgv[1]));
} }
// Handle the connection. // Handle the connection.
@ -264,27 +265,8 @@ static void daemonLoop(char * * argv)
} }
} }
static void runDaemon(bool stdio)
static int main_nix_daemon(int argc, char * * argv)
{ {
{
auto stdio = false;
parseCmdLine(argc, argv, [&](Strings::iterator & arg, const Strings::iterator & end) {
if (*arg == "--daemon")
; // ignored for backwards compatibility
else if (*arg == "--help")
showManPage("nix-daemon");
else if (*arg == "--version")
printVersion("nix-daemon");
else if (*arg == "--stdio")
stdio = true;
else return false;
return true;
});
initPlugins();
if (stdio) { if (stdio) {
if (auto store = openUncachedStore().dynamic_pointer_cast<RemoteStore>()) { if (auto store = openUncachedStore().dynamic_pointer_cast<RemoteStore>()) {
auto conn = store->openConnectionWrapper(); auto conn = store->openConnectionWrapper();
@ -311,7 +293,7 @@ static int main_nix_daemon(int argc, char * * argv)
if (res == -1) if (res == -1)
throw SysError("splicing data from stdin to daemon socket"); throw SysError("splicing data from stdin to daemon socket");
else if (res == 0) else if (res == 0)
return 0; return;
} }
} }
} else { } else {
@ -322,12 +304,58 @@ static int main_nix_daemon(int argc, char * * argv)
not `nix-daemon`'s responsibility. */ not `nix-daemon`'s responsibility. */
processConnection(openUncachedStore(), from, to, Trusted, NotRecursive, [&](Store & _){}); processConnection(openUncachedStore(), from, to, Trusted, NotRecursive, [&](Store & _){});
} }
} else { } else
daemonLoop(argv); daemonLoop();
} }
static int main_nix_daemon(int argc, char * * argv)
{
{
auto stdio = false;
parseCmdLine(argc, argv, [&](Strings::iterator & arg, const Strings::iterator & end) {
if (*arg == "--daemon")
; // ignored for backwards compatibility
else if (*arg == "--help")
showManPage("nix-daemon");
else if (*arg == "--version")
printVersion("nix-daemon");
else if (*arg == "--stdio")
stdio = true;
else return false;
return true;
});
initPlugins();
runDaemon(stdio);
return 0; return 0;
} }
} }
static RegisterLegacyCommand r_nix_daemon("nix-daemon", main_nix_daemon); static RegisterLegacyCommand r_nix_daemon("nix-daemon", main_nix_daemon);
struct CmdDaemon : StoreCommand
{
std::string description() override
{
return "daemon to perform store operations on behalf of non-root clients";
}
Category category() override { return catUtility; }
std::string doc() override
{
return
#include "daemon.md"
;
}
void run(ref<Store> store) override
{
runDaemon(false);
}
};
static auto rCmdDaemon = registerCommand2<CmdDaemon>({"daemon"});

21
src/nix/daemon.md Normal file
View file

@ -0,0 +1,21 @@
R""(
# Example
* Run the daemon in the foreground:
```console
# nix daemon
```
# Description
This command runs the Nix daemon, which is a required component in
multi-user Nix installations. It performs build actions and other
operations on the Nix store on behalf of non-root users. Usually you
don't run the daemon directly; instead it's managed by a service
management framework such as `systemd`.
Note that this daemon does not fork into the background.
)""

View file

@ -52,6 +52,7 @@ static bool haveInternet()
} }
std::string programPath; std::string programPath;
char * * savedArgv;
struct NixArgs : virtual MultiCommand, virtual MixCommonArgs struct NixArgs : virtual MultiCommand, virtual MixCommonArgs
{ {
@ -232,6 +233,8 @@ static auto rCmdHelp = registerCommand<CmdHelp>("help");
void mainWrapped(int argc, char * * argv) void mainWrapped(int argc, char * * argv)
{ {
savedArgv = argv;
/* The chroot helper needs to be run before any threads have been /* The chroot helper needs to be run before any threads have been
started. */ started. */
if (argc > 0 && argv[0] == chrootHelperName) { if (argc > 0 && argv[0] == chrootHelperName) {

View file

@ -73,7 +73,7 @@ startDaemon() {
# Start the daemon, wait for the socket to appear. !!! # Start the daemon, wait for the socket to appear. !!!
# nix-daemon should have an option to fork into the background. # nix-daemon should have an option to fork into the background.
rm -f $NIX_STATE_DIR/daemon-socket/socket rm -f $NIX_STATE_DIR/daemon-socket/socket
nix-daemon & nix daemon &
for ((i = 0; i < 30; i++)); do for ((i = 0; i < 30; i++)); do
if [ -e $NIX_DAEMON_SOCKET_PATH ]; then break; fi if [ -e $NIX_DAEMON_SOCKET_PATH ]; then break; fi
sleep 1 sleep 1