r4596 - trunk/varnish-cache/bin/varnishadm
phk at projects.linpro.no
phk at projects.linpro.no
Fri Feb 26 20:17:58 CET 2010
Author: phk
Date: 2010-02-26 20:17:57 +0100 (Fri, 26 Feb 2010)
New Revision: 4596
Modified:
trunk/varnish-cache/bin/varnishadm/varnishadm.1
trunk/varnish-cache/bin/varnishadm/varnishadm.c
Log:
Add a "pass" mode, where varnishadm just passes your commands,
but does handle the -S authentication for you.
You can now get a secure remote CLI connection by:
ssh foohost varnisadm -T :8081 -S/etc/varnish_secret
Or you can:
echo "help" | ssh foohost varnisadm -T :8081 -S/etc/varnish_secret
Modified: trunk/varnish-cache/bin/varnishadm/varnishadm.1
===================================================================
--- trunk/varnish-cache/bin/varnishadm/varnishadm.1 2010-02-26 19:16:39 UTC (rev 4595)
+++ trunk/varnish-cache/bin/varnishadm/varnishadm.1 2010-02-26 19:17:57 UTC (rev 4596)
@@ -39,21 +39,40 @@
.Op Fl t Ar timeout
.Op Fl S Ar secret_file
.Fl T Ar address Ns : Ns Ar port
-.Cm command
-.Op Ar ...
+.Op Cm command Op Ar ...
.Sh DESCRIPTION
The
.Nm
-utility sends the given command and arguments to the
-.Xr varnishd 1
-instance at the specified address and port and prints the results.
+utility establishes a CLI connection using the
+.Fl T
+and
+.Fl S
+arguments.
.Pp
+If a
+.Cm command
+is given, the command and arguments are sent over the
+CLI connection and the result returned on stdout.
+.Pp
+If no
+.Cm command
+argument is given
+.Nm
+will pass commands and replies between the CLI socket and
+stdin/stdout.
+.Pp
The following options are available:
.Bl -tag -width Fl
.It Fl t Ar timeout
Wait no longer than this many seconds for an operation to finish.
.It Fl S Ar secret_file
-Specify the authentication secret file
+Specify the authentication secret file.
+.Pp
+This should be the same -S argument as was given to
+.Nm varnishd .
+.Pp
+Only processes which can read the contents of this file, will be able
+to authenticate the CLI connection.
.It Fl T Ar address Ns : Ns Ar port
Connect to the management interface at the specified address and port.
.El
@@ -67,9 +86,20 @@
.Cm param.show
command.
.Sh EXIT STATUS
-The exit status of the
+If a
+.Cm command
+is given,
+the exit status of the
.Nm
utility is zero if the command succeeded, and non-zero otherwise.
+.Sh EXAMPLES
+Some ways you can use varnishadm:
+.Pp
+.Dl varnishadm -T localhost:999 -S /var/db/secret vcl.use foo
+.Pp
+.Dl echo vcl.use foo | varnishadm -T localhost:999 -S /var/db/secret
+.Pp
+.Dl echo vcl.use foo | ssh vhost varnishadm -T localhost:999 -S /var/db/secret
.Sh SEE ALSO
.Xr varnishd 1
.Sh HISTORY
Modified: trunk/varnish-cache/bin/varnishadm/varnishadm.c
===================================================================
--- trunk/varnish-cache/bin/varnishadm/varnishadm.c 2010-02-26 19:16:39 UTC (rev 4595)
+++ trunk/varnish-cache/bin/varnishadm/varnishadm.c 2010-02-26 19:17:57 UTC (rev 4596)
@@ -33,11 +33,14 @@
SVNID("$Id$")
#include <fcntl.h>
+#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
+#include <sys/socket.h>
+
#include "cli.h"
#include "cli_common.h"
#include "libvarnish.h"
@@ -45,16 +48,29 @@
static double timeout = 5;
+static void
+cli_write(int sock, const char *s)
+{
+ int i, l;
+
+ i = strlen(s);
+ l = write (sock, s, i);
+ if (i == l)
+ return;
+ perror("Write error CLI socket");
+ exit (1);
+}
+
/*
* This function establishes a connection to the specified ip and port and
* sends a command to varnishd. If varnishd returns an OK status, the result
* is printed and 0 returned. Else, an error message is printed and 1 is
* returned
*/
-static void
-telnet_mgt(const char *T_arg, const char *S_arg, int argc, char *argv[])
+static int
+cli_sock(const char *T_arg, const char *S_arg)
{
- int i, fd;
+ int fd;
int sock;
unsigned status;
char *answer = NULL;
@@ -66,7 +82,7 @@
exit(1);
}
- cli_readres(sock, &status, &answer, timeout);
+ (void)cli_readres(sock, &status, &answer, timeout);
if (status == CLIS_AUTH) {
if (S_arg == NULL) {
fprintf(stderr, "Authentication required\n");
@@ -80,58 +96,125 @@
}
CLI_response(fd, answer, buf);
AZ(close(fd));
- write(sock, "auth ", 5);
- write(sock, buf, strlen(buf));
- write(sock, "\n", 1);
- cli_readres(sock, &status, &answer, timeout);
+ free(answer);
+
+ cli_write(sock, "auth ");
+ cli_write(sock, buf);
+ cli_write(sock, "\n");
+ (void)cli_readres(sock, &status, &answer, timeout);
}
if (status != CLIS_OK) {
fprintf(stderr, "Rejected %u\n%s\n", status, answer);
exit(1);
}
+ free(answer);
- write(sock, "ping\n", 5);
- cli_readres(sock, &status, &answer, timeout);
+ cli_write(sock, "ping\n");
+ (void)cli_readres(sock, &status, &answer, timeout);
if (status != CLIS_OK || strstr(answer, "PONG") == NULL) {
fprintf(stderr, "No pong received from server\n");
exit(1);
}
free(answer);
+ return (sock);
+}
+
+static void
+do_args(int sock, int argc, char * const *argv)
+{
+ int i;
+ unsigned status;
+ char *answer = NULL;
+
for (i=0; i<argc; i++) {
+ /* XXX: We should really CLI-quote these */
if (i > 0)
- write(sock, " ", 1);
- write(sock, argv[i], strlen(argv[i]));
+ cli_write(sock, " ");
+ cli_write(sock, argv[i]);
}
- write(sock, "\n", 1);
+ cli_write(sock, "\n");
- cli_readres(sock, &status, &answer, 2000);
+ (void)cli_readres(sock, &status, &answer, 2000);
- close(sock);
+ /* XXX: AZ() ? */
+ (void)close(sock);
+ printf("%s\n", answer);
if (status == CLIS_OK) {
- printf("%s\n", answer);
exit(0);
}
fprintf(stderr, "Command failed with error code %u\n", status);
exit(1);
+}
+/*
+ * No arguments given, simply pass bytes on stdin/stdout and CLI socket
+ * Send a "banner" to varnish, to provoke a welcome message.
+ */
+static void
+pass(int sock)
+{
+ struct pollfd fds[2];
+ char buf[1024];
+ int i, n, m;
+
+ cli_write(sock, "banner\n");
+ fds[0].fd = sock;
+ fds[0].events = POLLIN;
+ fds[1].fd = 0;
+ fds[1].events = POLLIN;
+ while (1) {
+ i = poll(fds, 2, -1);
+ assert(i > 0);
+ if (fds[0].revents & POLLIN) {
+ n = read(fds[0].fd, buf, sizeof buf);
+ if (n == 0)
+ exit (0);
+ if (n < 0) {
+ perror("Read error reading CLI socket");
+ exit (0);
+ }
+ assert(n > 0);
+ m = write(1, buf, n);
+ if (n != m) {
+ perror("Write error writing stdout");
+ exit (1);
+ }
+ }
+ if (fds[1].revents & POLLIN) {
+ n = read(fds[1].fd, buf, sizeof buf);
+ if (n == 0) {
+ AZ(shutdown(sock, SHUT_WR));
+ fds[1].fd = -1;
+ } else if (n < 0) {
+ exit(0);
+ } else {
+ m = write(sock, buf, n);
+ if (n != m) {
+ perror("Write error writing CLI socket");
+ exit (1);
+ }
+ }
+ }
+ }
}
static void
usage(void)
{
fprintf(stderr,
- "usage: varnishadm [-t timeout] [-S secretfile] -T [address]:port command [...]\n");
+ "usage: varnishadm [-t timeout] [-S secretfile] "
+ "-T [address]:port command [...]\n");
exit(1);
}
int
-main(int argc, char *argv[])
+main(int argc, char * const *argv)
{
const char *T_arg = NULL;
const char *S_arg = NULL;
- int opt;
+ int opt, sock;
while ((opt = getopt(argc, argv, "S:T:t:")) != -1) {
switch (opt) {
@@ -152,10 +235,16 @@
argc -= optind;
argv += optind;
- if (T_arg == NULL || argc < 1)
+ if (T_arg == NULL)
usage();
- telnet_mgt(T_arg, S_arg, argc, argv);
+ assert(T_arg != NULL);
+ sock = cli_sock(T_arg, S_arg);
+ if (argc > 0)
+ do_args(sock, argc, argv);
+ else
+ pass(sock);
+
exit(0);
}
More information about the varnish-commit
mailing list