Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 11/06/2019, à 16:21

FanfanPopo

Permissions scripts : uniquement executable par tout le monde

Bonjour,
j'ai créé un script en root. Je souhaiterais que seul l'utilisateur root puisse lire et écrire dans ce script. Les autres utilisateurs peuvent uniquement l'executer. L'objectif est que les utilisateurs non root puissent executer le script sans pouvoir le lire.
J'ai essayé

sudo chmod 711 script.sh

Voici le résultat du ls -l :

-rwx--x--x 1 root root 24 juin 11 17:01 script.sh

Cependant, l'utilisateur non root ne peut pas l'éxecuter.

/bin/bash : ./script.sh: Permission non accordée

J'ai effectué quelques recherches mais n'ai pas trouvé de solution à mon problème.
Avez-vous une idée ?

Hors ligne

#2 Le 11/06/2019, à 18:06

Watael

Re : Permissions scripts : uniquement executable par tout le monde

salut,

pour exécuter un script, il faut impérativement pouvoir le lire.


Connected \o/
Welcome to sHell. · eval is evil.

Hors ligne

#3 Le 11/06/2019, à 18:13

pingouinux

Re : Permissions scripts : uniquement executable par tout le monde

Bonsoir,
Tu peux regarder cette discussion de 2012, notamment mon message #7, auquel je n'ai jamais reçu de réponse :
Interdire lecture d'un script a un utilisateur
Le lien qui y figure ne semble plus actif.

Il s'agit d'utiliser setuid, mais ce n'est pas possible sur un script. Il faut ruser en utilisant setuid sur un lanceur écrit en C qui va appeler le script, et les utilisateurs appelleront le lanceur.

man setuid

Hors ligne

#4 Le 11/06/2019, à 22:34

kamaris

Re : Permissions scripts : uniquement executable par tout le monde

@pingouinux : le code donné dans ton lien nécessite une petite modif, depuis Ubuntu 16.04 semble-t-il, car le comportement par défaut de dash a alors été changé pour coller à celui de bash concernant le traitement du suid : https://unix.stackexchange.com/question … nsistently

Ceci dit, comme il est finalement conseillé dans ce lien ou dans celui-ci, ne vaut-il pas mieux de toutes façons utiliser la fonctionnalité offerte par sudo d'exécuter une commande spécifique sans mot de passe ?

Hors ligne

#5 Le 12/06/2019, à 08:46

pingouinux

Re : Permissions scripts : uniquement executable par tout le monde

@kamaris #4 : Effectivement, je viens de faire un test, et ça ne marche plus

$ cat lanceur.c
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>

int main() {
  printf("UID=%d EUID=%d\n",getuid(),geteuid());
  system("./mon_script.sh");
}

$ make lanceur
cc     lanceur.c   -o lanceur

$ sudo chown root:root lanceur
$ sudo chmod 4705 lanceur

$ ls -l lanceur mon_script.sh
-rws---r-x 1 root root 8768 Jun 12 09:41 lanceur
-rwx------ 1 root root   62 Jun 12 09:30 mon_script.sh

$ ./lanceur
UID=1000 EUID=0
sh: 1: ./mon_script.sh: Permission denied

Dernière modification par pingouinux (Le 12/06/2019, à 09:15)

Hors ligne

#6 Le 12/06/2019, à 10:45

kamaris

Re : Permissions scripts : uniquement executable par tout le monde

Oui, comme dit dans une réponse du lien ci-dessus, il faut ajouter un bout de code pour forcer l'uid à rester sur l'euid, car system() appelle sh qui pointe vers dash :

:~$ cat lanceur.c
#define _GNU_SOURCE
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>

int main() {
	uid_t euid = geteuid();
	gid_t egid = getegid();
	setresgid(egid, egid, egid);
	setresuid(euid, euid, euid);
	printf("UID=%d EUID=%d\n",getuid(),geteuid());
	system("./script.sh");
}
:~$ sudo cat script.sh 
#!/bin/bash

echo "ok"
:~$ make lanceur
cc     lanceur.c   -o lanceur
:~$ sudo chown root:root lanceur
:~$ sudo chmod 4701 lanceur
:~$ ls -l lanceur script.sh
-rws-----x 1 root root 16760 juin  12 11:34 lanceur
-rwx------ 1 root root    23 juin  12 11:30 script.sh
:~$ ./lanceur
UID=0 EUID=0
ok
:~$

Par contre, encore une fois, l'usage de sudo en éditant /etc/sudoers est surement préférable pour faire ce que veut faire @FanfanPopo.

Hors ligne

#7 Le 12/06/2019, à 12:43

pingouinux

Re : Permissions scripts : uniquement executable par tout le monde

Merci kamaris. J'ai testé ton lanceur avec succès, et le note sur mes tablettes.

Je ne savais pas qu'un exécutable n'a pas besoin de la permission de lecture, et que l'exécution suffit.
Dans notre cas, il suffit de :

$ sudo chmod 4101 lanceur
$ ls -l lanceur
---s-----x 1 root root 8976 Jun 12 13:27 lanceur

Hors ligne

#8 Le 12/06/2019, à 13:07

kamaris

Re : Permissions scripts : uniquement executable par tout le monde

Oui effectivement, les droits de lecture (et à fortiori d'écriture) ne sont pas non plus nécessaires pour root. Je suis loin de maitriser toutes les subtilités de la chose, mais comme on s'en doute, c'est parce que l'exécutable est chargé directement dans le noyau, au contraire du script qui doit être lu par l'interpréteur, comme il est dit par exemple dans cette autre lien unix.stackexchange.

Tant qu'on y est, j'ajoute ici une autre version de lanceur.c qui fonctionne aussi (glanée et adaptée à partir d'un lien que je ne retrouve plus), sans s'embêter avec ces histoires de sh/dash, car on peut cette fois utiliser l'option -p de bash :

:~$ cat lanceur.c 
#include <unistd.h> 

int main () {
    char* arr[] = {"bash", "-p", "./script.sh", NULL};
    return execv("/bin/bash", arr);
}
:~$ 

Dernière modification par kamaris (Le 12/06/2019, à 13:11)

Hors ligne

#9 Le 12/06/2019, à 14:47

LeoMajor

Re : Permissions scripts : uniquement executable par tout le monde

bonjour,

utilise shc - Generic shell script compiler
très simple et efficace

sudo apt/aptitude install shc 

exemple;

nano ~/scripts/test_instructions.bash
..

#!/bin/bash
declare -a nums rnums
echo "bonjour"
if [ "$EUID" -ne 0 ]; then printf "%s\n" "vous n'êtes pas root" ; else echo -e "\tcontinue\n"; fi
test -f "$0" && file "$0"
for ((i=1; i<=5; i++)); do nums+=("$i"); done
rnums=($(sort -r < <(printf "%d\n" ${nums[*]})))
declare -p nums
declare -p rnums

exit 9
chmod +x ~/scripts/test_instructions.bash

jusque là le script fonctionne normalement soit par ./scripts/test_instructions.bash ou bash  /scripts/test_instructions.bash
le fichier est parfaitement lisible

après cela se complique

shc -f  ~/scripts/test_instructions.bash

qui génère

ls -ls ~/scripts/test_instructions.bash*
 4 -rwxr-xr-x 1 toto ...  /home/toto/scripts/test_instructions.bash
12 -rwx--x--x 1 toto ... /home/toto/scripts/test_instructions.bash.x
12 -rw-r--r-- 1 toto ...  /home/toto/scripts/test_instructions.bash.x.c

A/ /home/toto/scripts/test_instructions.bash est le fichier original qui fonctionne de manière classique
B/ le deuxième, est un binaire

:~$ ./scripts/test_instructions.bash.x
bonjour
vous n'êtes pas root
./scripts/test_instructions.bash.x: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 2.6.32, BuildID[sha1]=f456c047690b4111dab6e80bf0c07dc2ca22fa92, stripped
declare -a nums='([0]="1" [1]="2" [2]="3" [3]="4" [4]="5")'
declare -a rnums='([0]="5" [1]="4" [2]="3" [3]="2" [4]="1")'

ou

sudo ./scripts/test_instructions.bash.x
[sudo] Mot de passe de toto : ... 
bonjour
	continue

./scripts/test_instructions.bash.x: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 2.6.32, BuildID[sha1]=f456c047690b4111dab6e80bf0c07dc2ca22fa92, stripped
declare -a nums='([0]="1" [1]="2" [2]="3" [3]="4" [4]="5")'
declare -a rnums='([0]="5" [1]="4" [2]="3" [3]="2" [4]="1")'

le binaire fonctionne parfaitement mais évidemment parfaitement illisible pour retrouver le script d'origine.
tu peux le vérifier avec hexdump, strings, od, objdump,  ... , il y n'y a pas de traces.

donc tu peux laisser ~/scripts/test_instructions.bash.x, accessible à tout le monde
Donc tu auras compris que ~/scripts/test_instructions.bash sera réservé à root, y compris shc

C/ le dernier fichier en C est le code qui sert à la compilation pour B/. 
cat ./scripts/test_instructions.bash.x.c

#if 0
	shc Version 3.8.9b, Generic Script Compiler
	Copyright (c) 1994-2015 Francisco Rosales <frosal@fi.upm.es>

	shc -f ./scripts/test_instructions.bash 
#endif

static  char data [] = 
#define      tst2_z	19
#define      tst2	((&data[0]))
	"\114\325\273\025\111\065\223\303\336\122\055\325\032\214\003\363"
	"\042\003\205\140"
#define      rlax_z	1
#define      rlax	((&data[20]))
	"\334"
#define      text_z	312
#define      text	((&data[62]))
	"\351\324\265\361\365\125\213\316\256\032\330\266\036\031\054\371"
	"\254\147\025\236\242\372\255\337\132\130\316\264\061\124\013\033"
	"\050\300\014\036\026\230\355\305\262\000\340\160\343\236\241\013"
	"\127\076\246\354\212\246\345\176\163\051\254\265\035\110\106\316"
	"\111\011\104\351\242\302\114\234\316\114\007\216\221\167\064\036"
	"\017\026\331\227\000\352\003\307\360\362\123\132\102\004\010\374"
	"\370\310\251\015\172\076\374\035\207\374\376\031\175\260\225\122"
	"\377\220\365\114\027\236\235\146\045\115\371\073\132\205\114\056"
	"\060\224\126\271\022\056\325\351\232\312\210\022\357\206\334\145"
	"\037\175\245\236\040\214\177\256\240\002\103\377\217\011\162\343"
	"\275\077\210\032\151\072\200\226\146\177\131\230\143\377\307\354"
	"\145\113\336\331\002\354\035\141\155\052\015\346\017\311\350\013"
	"\142\202\253\241\053\362\106\266\100\220\351\057\320\211\064\252"
	"\366\202\133\351\064\251\277\274\165\140\232\177\357\052\364\320"
	"\040\107\004\337\363\123\035\171\040\061\252\364\254\356\223\006"
	"\052\206\324\051\345\367\363\244\126\151\363\240\036\177\020\145"
	"\206\345\014\124\015\124\257\035\132\006\244\236\176\371\056\267"
	"\032\235\134\275\125\332\153\250\373\275\120\237\265\073\276\320"
	"\020\035\176\275\171\332\072\245\221\137\135\316\023\016\060\342"
	"\126\076\201\316\271\320\242\102\272\272\006\176\012\035\003\135"
	"\351\061\124\014\236\246\111\357\107\037\332\115\031\012\171\300"
	"\250\217\121\274\116\170\330\334\161\036\241\307\052\161\360\150"
	"\347\306\173\320\337\250\312\214\020\337\052\262\331\330\222\064"
	"\061\140\350\142\265\363\176\336\264\212\375"
#define      opts_z	1
#define      opts	((&data[400]))
	"\151"
#define      chk1_z	22
#define      chk1	((&data[406]))
	"\013\246\221\263\160\242\333\135\076\134\311\222\140\205\365\131"
	"\106\001\152\210\315\115\255\277\070\356\254\035\304\120\107"
#define      lsto_z	1
#define      lsto	((&data[432]))
	"\001"
#define      pswd_z	256
#define      pswd	((&data[456]))
	"\151\106\264\037\072\062\376\356\275\373\271\340\346\111\265\227"
	"\125\134\050\011\314\106\315\340\003\107\102\062\377\337\134\340"
	"\077\106\356\132\031\050\126\036\051\162\110\324\030\245\277\274"
	"\326\241\225\152\113\146\112\116\255\214\200\255\154\335\215\254"
	"\043\173\007\075\243\135\133\315\320\244\241\350\112\141\245\041"
	"\002\072\213\116\241\325\234\116\142\035\374\317\372\211\173\036"
	"\004\203\133\250\340\267\165\260\134\027\231\246\170\076\310\173"
	"\171\123\311\032\051\145\151\214\203\145\134\175\356\330\233\363"
	"\133\367\233\073\257\020\354\013\047\206\262\240\304\172\033\075"
	"\316\345\130\370\112\302\205\316\047\341\113\026\271\347\011\024"
	"\337\244\120\216\265\075\231\335\303\113\175\210\306\231\306\225"
	"\176\036\215\311\340\023\227\010\364\343\036\255\312\050\302\251"
	"\315\023\067\203\120\321\140\023\035\336\233\343\167\142\171\366"
	"\200\006\277\141\032\126\151\016\071\210\274\004\261\177\256\177"
	"\222\345\002\342\266\142\366\323\101\222\267\270\364\060\256\165"
	"\067\156\326\121\305\100\140\376\311\034\003\173\233\261\372\056"
	"\227\374\020\115\137\007\041\240\232\331\130\216\011\007\004\101"
	"\166\332\222\073\033\362\072\035\216\103\107\256\114\245\000\266"
	"\353\264\325\045\347\323\024\244\317\316\205"
#define      chk2_z	19
#define      chk2	((&data[732]))
	"\054\251\341\141\372\263\124\055\112\313\260\141\200\261\014\104"
	"\323\057\261\115"
#define      tst1_z	22
#define      tst1	((&data[755]))
	"\166\144\274\364\277\352\026\017\044\242\210\262\337\147\104\245"
	"\274\231\340\303\132\223\316\235\137\103\201"
#define      inlo_z	3
#define      inlo	((&data[779]))
	"\303\075\014"
#define      msg1_z	42
#define      msg1	((&data[791]))
	"\371\212\131\255\137\176\224\063\223\137\210\102\263\006\025\014"
	"\000\044\360\106\267\152\060\217\346\167\244\274\320\103\240\330"
	"\336\276\005\336\372\146\217\252\163\220\020\103\261\112\152\022"
	"\027\030\066\071\002\142\276"
#define      date_z	1
#define      date	((&data[837]))
	"\010"
#define      shll_z	10
#define      shll	((&data[840]))
	"\173\135\272\242\042\144\251\014\264\327\317\046\364"
#define      xecc_z	15
#define      xecc	((&data[853]))
	"\202\050\075\317\071\332\102\036\362\043\301\363\372\307\177\000"
	"\103\076"
#define      msg2_z	19
#define      msg2	((&data[873]))
	"\164\206\004\042\166\262\361\176\356\015\157\052\313\347\241\171"
	"\177\235\315\363\150\350\274\346\203\267"/* End of data[] */;
#define      hide_z	4096
#define DEBUGEXEC	0	/* Define as 1 to debug execvp calls */
#define TRACEABLE	0	/* Define as 1 to enable ptrace the executable */

/* rtc.c */

#include <sys/stat.h>
#include <sys/types.h>

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>

/* 'Alleged RC4' */

static unsigned char stte[256], indx, jndx, kndx;

/*
 * Reset arc4 stte. 
 */
void stte_0(void)
{
	indx = jndx = kndx = 0;
	do {
		stte[indx] = indx;
	} while (++indx);
}

/*
 * Set key. Can be used more than once. 
 */
void key(void * str, int len)
{
	unsigned char tmp, * ptr = (unsigned char *)str;
	while (len > 0) {
		do {
			tmp = stte[indx];
			kndx += tmp;
			kndx += ptr[(int)indx % len];
			stte[indx] = stte[kndx];
			stte[kndx] = tmp;
		} while (++indx);
		ptr += 256;
		len -= 256;
	}
}

/*
 * Crypt data. 
 */
void arc4(void * str, int len)
{
	unsigned char tmp, * ptr = (unsigned char *)str;
	while (len > 0) {
		indx++;
		tmp = stte[indx];
		jndx += tmp;
		stte[indx] = stte[jndx];
		stte[jndx] = tmp;
		tmp += stte[indx];
		*ptr ^= stte[tmp];
		ptr++;
		len--;
	}
}

/* End of ARC4 */

/*
 * Key with file invariants. 
 */
int key_with_file(char * file)
{
	struct stat statf[1];
	struct stat control[1];

	if (stat(file, statf) < 0)
		return -1;

	/* Turn on stable fields */
	memset(control, 0, sizeof(control));
	control->st_ino = statf->st_ino;
	control->st_dev = statf->st_dev;
	control->st_rdev = statf->st_rdev;
	control->st_uid = statf->st_uid;
	control->st_gid = statf->st_gid;
	control->st_size = statf->st_size;
	control->st_mtime = statf->st_mtime;
	control->st_ctime = statf->st_ctime;
	key(control, sizeof(control));
	return 0;
}

#if DEBUGEXEC
void debugexec(char * sh11, int argc, char ** argv)
{
	int i;
	fprintf(stderr, "shll=%s\n", sh11 ? sh11 : "<null>");
	fprintf(stderr, "argc=%d\n", argc);
	if (!argv) {
		fprintf(stderr, "argv=<null>\n");
	} else { 
		for (i = 0; i <= argc ; i++)
			fprintf(stderr, "argv[%d]=%.60s\n", i, argv[i] ? argv[i] : "<null>");
	}
}
#endif /* DEBUGEXEC */

void rmarg(char ** argv, char * arg)
{
	for (; argv && *argv && *argv != arg; argv++);
	for (; argv && *argv; argv++)
		*argv = argv[1];
}

int chkenv(int argc)
{
	char buff[512];
	unsigned long mask, m;
	int l, a, c;
	char * string;
	extern char ** environ;

	mask  = (unsigned long)&chkenv;
	mask ^= (unsigned long)getpid() * ~mask;
	sprintf(buff, "x%lx", mask);
	string = getenv(buff);
#if DEBUGEXEC
	fprintf(stderr, "getenv(%s)=%s\n", buff, string ? string : "<null>");
#endif
	l = strlen(buff);
	if (!string) {
		/* 1st */
		sprintf(&buff[l], "=%lu %d", mask, argc);
		putenv(strdup(buff));
		return 0;
	}
	c = sscanf(string, "%lu %d%c", &m, &a, buff);
	if (c == 2 && m == mask) {
		/* 3rd */
		rmarg(environ, &string[-l - 1]);
		return 1 + (argc - a);
	}
	return -1;
}

#if !defined(TRACEABLE)

#define _LINUX_SOURCE_COMPAT
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>

#if !defined(PTRACE_ATTACH) && defined(PT_ATTACH)
#	define PTRACE_ATTACH	PT_ATTACH
#endif
void untraceable(char * argv0)
{
	char proc[80];
	int pid, mine;

	switch(pid = fork()) {
	case  0:
		pid = getppid();
		/* For problematic SunOS ptrace */
#if defined(__FreeBSD__)
		sprintf(proc, "/proc/%d/mem", (int)pid);
#else
		sprintf(proc, "/proc/%d/as",  (int)pid);
#endif
		close(0);
		mine = !open(proc, O_RDWR|O_EXCL);
		if (!mine && errno != EBUSY)
			mine = !ptrace(PTRACE_ATTACH, pid, 0, 0);
		if (mine) {
			kill(pid, SIGCONT);
		} else {
			perror(argv0);
			kill(pid, SIGKILL);
		}
		_exit(mine);
	case -1:
		break;
	default:
		if (pid == waitpid(pid, 0, 0))
			return;
	}
	perror(argv0);
	_exit(1);
}
#endif /* !defined(TRACEABLE) */

char * xsh(int argc, char ** argv)
{
	char * scrpt;
	int ret, i, j;
	char ** varg;
	char * me = argv[0];

	stte_0();
	 key(pswd, pswd_z);
	arc4(msg1, msg1_z);
	arc4(date, date_z);
	if (date[0] && (atoll(date)<time(NULL)))
		return msg1;
	arc4(shll, shll_z);
	arc4(inlo, inlo_z);
	arc4(xecc, xecc_z);
	arc4(lsto, lsto_z);
	arc4(tst1, tst1_z);
	 key(tst1, tst1_z);
	arc4(chk1, chk1_z);
	if ((chk1_z != tst1_z) || memcmp(tst1, chk1, tst1_z))
		return tst1;
	ret = chkenv(argc);
	arc4(msg2, msg2_z);
	if (ret < 0)
		return msg2;
	varg = (char **)calloc(argc + 10, sizeof(char *));
	if (!varg)
		return 0;
	if (ret) {
		arc4(rlax, rlax_z);
		if (!rlax[0] && key_with_file(shll))
			return shll;
		arc4(opts, opts_z);
		arc4(text, text_z);
		arc4(tst2, tst2_z);
		 key(tst2, tst2_z);
		arc4(chk2, chk2_z);
		if ((chk2_z != tst2_z) || memcmp(tst2, chk2, tst2_z))
			return tst2;
		/* Prepend hide_z spaces to script text to hide it. */
		scrpt = malloc(hide_z + text_z);
		if (!scrpt)
			return 0;
		memset(scrpt, (int) ' ', hide_z);
		memcpy(&scrpt[hide_z], text, text_z);
	} else {			/* Reexecute */
		if (*xecc) {
			scrpt = malloc(512);
			if (!scrpt)
				return 0;
			sprintf(scrpt, xecc, me);
		} else {
			scrpt = me;
		}
	}
	j = 0;
	varg[j++] = argv[0];		/* My own name at execution */
	if (ret && *opts)
		varg[j++] = opts;	/* Options on 1st line of code */
	if (*inlo)
		varg[j++] = inlo;	/* Option introducing inline code */
	varg[j++] = scrpt;		/* The script itself */
	if (*lsto)
		varg[j++] = lsto;	/* Option meaning last option */
	i = (ret > 1) ? ret : 0;	/* Args numbering correction */
	while (i < argc)
		varg[j++] = argv[i++];	/* Main run-time arguments */
	varg[j] = 0;			/* NULL terminated array */
#if DEBUGEXEC
	debugexec(shll, j, varg);
#endif
	execvp(shll, varg);
	return shll;
}

int main(int argc, char ** argv)
{
#if DEBUGEXEC
	debugexec("main", argc, argv);
#endif
#if !defined(TRACEABLE)
	untraceable(argv[0]);
#endif
	argv[1] = xsh(argc, argv);
	fprintf(stderr, "%s%s%s: %s\n", argv[0],
		errno ? ": " : "",
		errno ? strerror(errno) : "",
		argv[1] ? argv[1] : "<null>"
	);
	return 1;
}

dans un contexte d'exploitation, ce dernier fichier est à supprimer

Dernière modification par LeoMajor (Le 12/06/2019, à 14:51)

Hors ligne

#10 Le 12/06/2019, à 17:10

melixgaro

Re : Permissions scripts : uniquement executable par tout le monde

bonjour,

Attention avec shc. Il y a une limite sur le nombre de caractère que peut contenir le script d'origine et surtout :

$ cat script.sh
#!/bin/bash
while true
do
sleep 0.01
done

Exécution du script bash d'origine

$ ./script.sh
$ ps faux | grep script.sh
melixgaro   27112  3.1  0.0   9564  3504 pts/59   S+   18:04   0:00  |   \_ /bin/bash ./script.sh

Exécution du script passé via shc (regardez tout au bout de la très longue ligne, c'est le copier-coller tel quel du ps)

$ ./script.sh.x
$ ps faux | grep script.sh
melixgaro    4396  2.6  0.0   9568  3572 pts/59   S+   18:05   0:00  |   \_ ./script.sh.x -c                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 #!/bin/bash   while true do sleep 0.01 done  ./script.sh.x

Linux depuis ~2007. Xubuntu seulement.

Hors ligne