diff --git a/doc/man/man1/scontrol.1 b/doc/man/man1/scontrol.1
index f4b9e41e685c4965c4636591b05778206c6c94e0..366e0f11d2521e51e1b2cc8510f9c02c6ca5a78d 100644
--- a/doc/man/man1/scontrol.1
+++ b/doc/man/man1/scontrol.1
@@ -86,6 +86,9 @@ record counts, etc.
 .TP
 \fIversion\fP
 Display the version number of scontrol being executed.
+.TP
+\fI!!\fP
+Repeat the last command executed.
 
 .SH "EXAMPLE"
 .eo
diff --git a/src/scontrol/scontrol.c b/src/scontrol/scontrol.c
index 00f913b8db0b3784bf4b00cf9ca092b765d0cf04..1f6d597f43e038e8c0cdf16ea90c807570dd33c3 100644
--- a/src/scontrol/scontrol.c
+++ b/src/scontrol/scontrol.c
@@ -115,19 +115,16 @@ main (int argc, char *argv[])
 	else
 		error_code = get_command (&input_field_count, input_fields);
 
-	while (1) {
-#if DEBUG_MODULE
+	while (error_code == 0) {
+#if DEBUG_MODULE > 1
 		dump_command (input_field_count, input_fields);
 #endif
-		error_code =
-			process_command (input_field_count, input_fields);
+		error_code = process_command (input_field_count, input_fields);
 		if (error_code != 0)
 			break;
 		if (exit_flag == 1)
 			break;
 		error_code = get_command (&input_field_count, input_fields);
-		if (error_code != 0)
-			break;
 	}			
 
 	exit (error_code);
@@ -142,10 +139,14 @@ main (int argc, char *argv[])
 void
 dump_command (int argc, char *argv[]) 
 {
-	int i;
+	int i, j;
 
 	for (i = 0; i < argc; i++) {
-		printf ("arg %d:%s:\n", i, argv[i]);
+		printf ("arg %d:%s:", i, argv[i]);
+		for (j = 0; argv[i][j] ; j++) {
+			printf ("%2x ", (unsigned)argv[i][j]);
+		}
+		printf ("\n");
 	}			
 }
 
@@ -161,6 +162,7 @@ get_command (int *argc, char **argv)
 {
 	static char *in_line;
 	static int in_line_size = 0;
+	static int last_in_line_size = 0;
 	int in_line_pos = 0;
 	int temp_char, i;
 
@@ -185,6 +187,20 @@ get_command (int *argc, char **argv)
 			break;
 		if (temp_char == (int) '\n')
 			break;
+		if ((temp_char == (int) '!') && (in_line_pos == 0)) {
+			temp_char = getchar();
+			if (temp_char == (int) '!') {
+				in_line_pos = last_in_line_size;
+				while (temp_char != (int) '\n')
+					temp_char = getchar();
+				break;
+			}
+			else {
+				in_line[in_line_pos++] = (char) temp_char;
+				in_line[in_line_pos++] = (char) temp_char;
+				continue;
+			}
+		}
 		if ((in_line_pos + 2) >= in_line_size) {
 			in_line_size += BUF_SIZE;
 			xrealloc (in_line, in_line_size);
@@ -197,11 +213,13 @@ get_command (int *argc, char **argv)
 			}	
 		}		
 		in_line[in_line_pos++] = (char) temp_char;
-	}			
+	}
+
 	in_line[in_line_pos] = (char) NULL;
+	last_in_line_size = in_line_pos;
 
 	for (i = 0; i < in_line_pos; i++) {
-		if (isspace ((int) in_line[i]))
+		if ((in_line[i] == '\0') && (isspace ((int) in_line[i])))
 			continue;
 		if (((*argc) + 1) > MAX_INPUT_FIELDS) {	/* really bogus input line */
 			fprintf (stderr, "%s: can not process over %d words as configured\n",
@@ -210,7 +228,7 @@ get_command (int *argc, char **argv)
 		}		
 		argv[(*argc)++] = &in_line[i];
 		for (i++; i < in_line_pos; i++) {
-			if (!isspace ((int) in_line[i]))
+			if ((in_line[i] != '\0') && (!isspace ((int) in_line[i])))
 				continue;
 			in_line[i] = (char) NULL;
 			break;
@@ -284,13 +302,13 @@ print_job (char * job_id_str)
 	}
 	else
 		error_code = slurm_load_jobs ((time_t) NULL, &job_buffer_ptr);
+
 	if (error_code) {
 		if (quiet_flag != 1)
 			slurm_perror ("slurm_load_jobs error");
 		return;
 	}
-	else if (error_code == 0)
-		old_job_buffer_ptr = job_buffer_ptr;
+	old_job_buffer_ptr = job_buffer_ptr;
 	
 	if (quiet_flag == -1)
 		printf ("last_update_time=%ld\n", (long) job_buffer_ptr->last_update);
@@ -389,8 +407,8 @@ print_node_list (char *node_list)
 			slurm_perror ("slurm_load_node error");
 		return;
 	}
-	else
-		old_node_info_ptr = node_info_ptr;
+
+	old_node_info_ptr = node_info_ptr;
 
 	if (quiet_flag == -1)
 		printf ("last_update_time=%ld, records=%d\n", 
@@ -452,8 +470,8 @@ print_part (char *partition_name)
 			slurm_perror ("slurm_load_partitions error");
 		return;
 	}
-	else
-		old_part_info_ptr = part_info_ptr;
+
+	old_part_info_ptr = part_info_ptr;
 
 	if (quiet_flag == -1)
 		printf ("last_update_time=%ld\n", (long) part_info_ptr->last_update);
@@ -490,6 +508,8 @@ print_step (char *job_step_id_str)
 	char *next_str;
 	job_step_info_response_msg_t *job_step_info_ptr;
 	job_step_info_t * job_step_ptr;
+	static uint32_t last_job_id = 0, last_step_id = 0;
+	static job_step_info_response_msg_t *old_job_step_info_ptr;
 
 	if (job_step_id_str) {
 		job_id = (uint32_t) strtol (job_step_id_str, &next_str, 10);
@@ -497,13 +517,36 @@ print_step (char *job_step_id_str)
 			step_id = (uint32_t) strtol (&next_str[1], NULL, 10);
 	}
 
-	error_code = slurm_get_job_steps ( (time_t) 0, job_id, step_id, &job_step_info_ptr);
+	if ((old_job_step_info_ptr) &&
+	    (last_job_id == job_id) && (last_step_id == step_id)) {
+		error_code = slurm_get_job_steps ( old_job_step_info_ptr->last_update,
+					job_id, step_id, &job_step_info_ptr);
+		if (error_code == 0)
+			slurm_free_job_step_info_response_msg (old_job_step_info_ptr);
+		else if (slurm_get_errno () == SLURM_NO_CHANGE_IN_DATA) {
+			job_step_info_ptr = old_job_step_info_ptr;
+			error_code = 0;
+			if (quiet_flag == -1)
+				printf ("slurm_get_job_steps no change in data\n");
+		}
+	}
+	else {
+		if (old_job_step_info_ptr)
+			slurm_free_job_step_info_response_msg (old_job_step_info_ptr);
+		error_code = slurm_get_job_steps ( (time_t) 0, 
+					job_id, step_id, &job_step_info_ptr);
+	}
+
 	if (error_code) {
 		if (quiet_flag != 1)
 			slurm_perror ("slurm_get_job_steps error");
 		return;
 	}
-	
+
+	old_job_step_info_ptr = job_step_info_ptr;
+	last_job_id = job_id;
+	last_step_id = step_id;
+
 	if (quiet_flag == -1)
 		printf ("last_update_time=%ld\n", (long) job_step_info_ptr->last_update);
 
@@ -518,8 +561,6 @@ print_step (char *job_step_id_str)
 		else
 			printf ("No job steps in the system\n");
 	}
-
-	slurm_free_job_step_info_response_msg (job_step_info_ptr);
 }
 
 
@@ -534,54 +575,45 @@ process_command (int argc, char *argv[])
 {
 	int error_code;
 
-	if ((strcmp_i (argv[0], "exit") == 0) ||
+	if (argc < 1) {
+		if (quiet_flag == -1)
+			fprintf(stderr, "no input");
+	}
+	else if ((strcmp_i (argv[0], "exit") == 0) ||
 	    (strcmp_i (argv[0], "quit") == 0)) {
 		if (argc > 1)
-			fprintf (stderr,
-				 "too many arguments for keyword:%s\n",
-				 argv[0]);
+			fprintf (stderr, "too many arguments for keyword:%s\n", argv[0]);
 		exit_flag = 1;
 
 	}
 	else if (strcmp_i (argv[0], "help") == 0) {
 		if (argc > 1)
-			fprintf (stderr,
-				 "too many arguments for keyword:%s\n",
-				 argv[0]);
+			fprintf (stderr, "too many arguments for keyword:%s\n",argv[0]);
 		usage ();
 
 	}
 	else if (strcmp_i (argv[0], "quiet") == 0) {
 		if (argc > 1)
-			fprintf (stderr,
-				 "too many arguments for keyword:%s\n",
-				 argv[0]);
+			fprintf (stderr, "too many arguments for keyword:%s\n", argv[0]);
 		quiet_flag = 1;
 
 	}
 	else if (strncmp_i (argv[0], "reconfigure", 7) == 0) {
 		if (argc > 2)
-			fprintf (stderr,
-				 "too many arguments for keyword:%s\n",
-				 argv[0]);
+			fprintf (stderr, "too many arguments for keyword:%s\n", argv[0]);
 		error_code = slurm_reconfigure ();
 		if ((error_code != 0) && (quiet_flag != 1))
-			fprintf (stderr, "error %d from reconfigure\n",
-				 error_code);
+			fprintf (stderr, "error %d from reconfigure\n", error_code);
 
 	}
 	else if (strcmp_i (argv[0], "show") == 0) {
 		if (argc > 3) {
 			if (quiet_flag != 1)
-				fprintf (stderr,
-					 "too many arguments for keyword:%s\n",
-					 argv[0]);
+				fprintf (stderr, "too many arguments for keyword:%s\n", argv[0]);
 		}
 		else if (argc < 2) {
 			if (quiet_flag != 1)
-				fprintf (stderr,
-					 "too few arguments for keyword:%s\n",
-					 argv[0]);
+				fprintf (stderr, "too few arguments for keyword:%s\n", argv[0]);
 		}
 		else if (strncmp_i (argv[1], "config", 3) == 0) {
 			if (argc > 2)
@@ -933,6 +965,7 @@ usage () {
 	printf ("     update <SPECIFICATIONS>  update job, node, or partition configuration.\n");
 	printf ("     verbose                  enable detailed logging.\n");
 	printf ("     version                  display tool version number.\n");
+	printf ("     !!                       Repeat the last command entered.\n");
 	printf ("  <ENTITY> may be \"config\", \"job\", \"node\", \"partition\" or \"step\".\n");
 	printf ("  <ID> may be a configuration parametername , job id, node name, partition name or job step id.\n");
 	printf ("     Node names mayspecified using simple regular expressions, (e.g. \"lx[10-20]\").\n");