forked from lix-project/lix
Add 'nix daemon' command
This commit is contained in:
parent
28ef6ebf91
commit
7a472a76d4
|
@ -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;
|
||||||
|
|
|
@ -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,6 +265,48 @@ static void daemonLoop(char * * argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void runDaemon(bool stdio)
|
||||||
|
{
|
||||||
|
if (stdio) {
|
||||||
|
if (auto store = openUncachedStore().dynamic_pointer_cast<RemoteStore>()) {
|
||||||
|
auto conn = store->openConnectionWrapper();
|
||||||
|
int from = conn->from.fd;
|
||||||
|
int to = conn->to.fd;
|
||||||
|
|
||||||
|
auto nfds = std::max(from, STDIN_FILENO) + 1;
|
||||||
|
while (true) {
|
||||||
|
fd_set fds;
|
||||||
|
FD_ZERO(&fds);
|
||||||
|
FD_SET(from, &fds);
|
||||||
|
FD_SET(STDIN_FILENO, &fds);
|
||||||
|
if (select(nfds, &fds, nullptr, nullptr, nullptr) == -1)
|
||||||
|
throw SysError("waiting for data from client or server");
|
||||||
|
if (FD_ISSET(from, &fds)) {
|
||||||
|
auto res = splice(from, nullptr, STDOUT_FILENO, nullptr, SSIZE_MAX, SPLICE_F_MOVE);
|
||||||
|
if (res == -1)
|
||||||
|
throw SysError("splicing data from daemon socket to stdout");
|
||||||
|
else if (res == 0)
|
||||||
|
throw EndOfFile("unexpected EOF from daemon socket");
|
||||||
|
}
|
||||||
|
if (FD_ISSET(STDIN_FILENO, &fds)) {
|
||||||
|
auto res = splice(STDIN_FILENO, nullptr, to, nullptr, SSIZE_MAX, SPLICE_F_MOVE);
|
||||||
|
if (res == -1)
|
||||||
|
throw SysError("splicing data from stdin to daemon socket");
|
||||||
|
else if (res == 0)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
FdSource from(STDIN_FILENO);
|
||||||
|
FdSink to(STDOUT_FILENO);
|
||||||
|
/* Auth hook is empty because in this mode we blindly trust the
|
||||||
|
standard streams. Limiting access to those is explicitly
|
||||||
|
not `nix-daemon`'s responsibility. */
|
||||||
|
processConnection(openUncachedStore(), from, to, Trusted, NotRecursive, [&](Store & _){});
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
daemonLoop();
|
||||||
|
}
|
||||||
|
|
||||||
static int main_nix_daemon(int argc, char * * argv)
|
static int main_nix_daemon(int argc, char * * argv)
|
||||||
{
|
{
|
||||||
|
@ -285,49 +328,34 @@ static int main_nix_daemon(int argc, char * * argv)
|
||||||
|
|
||||||
initPlugins();
|
initPlugins();
|
||||||
|
|
||||||
if (stdio) {
|
runDaemon(stdio);
|
||||||
if (auto store = openUncachedStore().dynamic_pointer_cast<RemoteStore>()) {
|
|
||||||
auto conn = store->openConnectionWrapper();
|
|
||||||
int from = conn->from.fd;
|
|
||||||
int to = conn->to.fd;
|
|
||||||
|
|
||||||
auto nfds = std::max(from, STDIN_FILENO) + 1;
|
|
||||||
while (true) {
|
|
||||||
fd_set fds;
|
|
||||||
FD_ZERO(&fds);
|
|
||||||
FD_SET(from, &fds);
|
|
||||||
FD_SET(STDIN_FILENO, &fds);
|
|
||||||
if (select(nfds, &fds, nullptr, nullptr, nullptr) == -1)
|
|
||||||
throw SysError("waiting for data from client or server");
|
|
||||||
if (FD_ISSET(from, &fds)) {
|
|
||||||
auto res = splice(from, nullptr, STDOUT_FILENO, nullptr, SSIZE_MAX, SPLICE_F_MOVE);
|
|
||||||
if (res == -1)
|
|
||||||
throw SysError("splicing data from daemon socket to stdout");
|
|
||||||
else if (res == 0)
|
|
||||||
throw EndOfFile("unexpected EOF from daemon socket");
|
|
||||||
}
|
|
||||||
if (FD_ISSET(STDIN_FILENO, &fds)) {
|
|
||||||
auto res = splice(STDIN_FILENO, nullptr, to, nullptr, SSIZE_MAX, SPLICE_F_MOVE);
|
|
||||||
if (res == -1)
|
|
||||||
throw SysError("splicing data from stdin to daemon socket");
|
|
||||||
else if (res == 0)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
FdSource from(STDIN_FILENO);
|
|
||||||
FdSink to(STDOUT_FILENO);
|
|
||||||
/* Auth hook is empty because in this mode we blindly trust the
|
|
||||||
standard streams. Limiting access to those is explicitly
|
|
||||||
not `nix-daemon`'s responsibility. */
|
|
||||||
processConnection(openUncachedStore(), from, to, Trusted, NotRecursive, [&](Store & _){});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
daemonLoop(argv);
|
|
||||||
}
|
|
||||||
|
|
||||||
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
21
src/nix/daemon.md
Normal 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.
|
||||||
|
|
||||||
|
)""
|
|
@ -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) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue