Se afișează postările cu eticheta Linux. Afișați toate postările
Se afișează postările cu eticheta Linux. Afișați toate postările

07 august 2025

Kill process in Windows & Linux

Windows:

> netstat -ano | findstr :8080

> taskkill PID <pid> /F


Linux:

> sudo lsof -i 8080

> sudo kill -9 <pid>

07 august 2024

Script bash pt build proiecte

 ./script.sh <nume branch>

branch="master"
if [ -n "$1" ]; then
branch=$1
fi

printf "\ngit pull from "$branch"\n\n"

currentDate=`date +"%Y-%m-%d-%H%M"`
filename="$currentDate.log"
touch $filename

for dir in `ls .`;
do
if [[ -d $dir ]]; then
echo $'\n'$dir
cd $dir
mvn clean &>> ../$filename
git checkout master
git pull
cd ..
echo $'\n' &>> $filename
fi
done


# legacy first
echo $'\n' >> $filename
for dir in `ls .`;
do
if [[ -d $dir && "$dir" == *"legacy"* ]]; then
echo $'\n'$dir
cd $dir
mvn install -DskipTests &>> ../$filename
cd ..
echo $'\n' &>> $filename
fi
done

printf "\n"
for dir in `ls .`;
do
if [[ -d $dir && "$dir" != *"legacy"* ]]; then
echo $'\n'$dir
cd $dir
mvn install -DskipTests &>> ../$filename
cd ..
echo $'\n' &>> $filename
fi
done

13 decembrie 2023

Unix/networking interview questions

Lista proceselor in executie:

> px aux

> ps -l

> ps -e


Get thread dump of running Java processes:

> jps -lv      # afla [pid] proces java

> kill -3 [pid]


GREP - cauta linii in fisier text folosind un regex

> cat file.txt | grep "Cauta un rand"


TAIL - tipareste ultimele linii dintr-un fisier (default ultimele 10)

> cat file.txt | tail -n 2


LESS - afiseaza cate o pagina (nu incarca tot)

> less file.txt

> cat file.txt | less -p "pattern"   # afiseaza de la acel rand incolo


MORE - la fel ca LESS, insa navigarea inapoi e limitata si nu are optiuni de cautare 


Diferenta TCP si UDP

TCP = transmission control protocol, bazat pe conexiune, de incredere dar mai lent, verificare buna de erori. Potrivit pt transmitere de texte, fisiere, navigare pe internet.

UDP = user datagram protocol, fara conexiune, rapid dar pierde date (nu retransmite), verificare minimala de erori, permite broadcasting. Potrivit pt transmitere continut media (video, audio), jocuri in retea.

In caz de coliziune, ruterele prefera pachetele TCP si renunta la cele UDP.


Aflare spatiu liber pe disc:

> df


Aflare marime folder

> du

01 noiembrie 2016

FDISK comenzi pt repartitionarea unui memory stick, in Linux

Afisare toate partitiile:
> lsblk
Sa spunem ca /dev/sdc reprezinta flash-ul.

Stergere totala:
> dd if=/dev/zero of=/dev/sdc bs=512 count=1

Refacere structura unui flash drive:
> fdisk /dev/sdc
  > m   (toate comenzile)
  > n    (partitie noua)
  > p    (primary partition)
  > 1    (index, adica sdc1)
  (o singura partitie care sa ocupe tot discul)
  > t     (change partition type)
  > L    (list all, perhaps choose option #4 FAT16 <32M)
  > p     (print current config)
  > w    (write)

Daca apare eroare dupa write:
> sudo partprobe /dev/sdc

30 septembrie 2016

Linux: mount USB

> sudo fdisk -l
> sudo mkdir /media/usb
> sudo mount /dev/sdb1 /media/usb

> sudo umount /media/usb


21 septembrie 2016

Valgrind (notite)

VALGRIND
tools available: memcheck (for memory leaks), cachegrind (detects cache misses), massif (heap and stack profiling), helgrind, callgrind, DRD
- cannot be attached to a already running process (Valgrind wants to have full control from the very start)
- results are given for the whole process but you can find the errors coming from a specific shared object
Memcheck
> valgrind --tool=memcheck --leak-check=yes --track-children=yes --log-file=log.txt java Example
Types of errors (counting the occurrences):
  • illegal read/write
    cat log.txt | grep "Invalid" | wc -l
  • use of uninitialised values
    cat log.txt | grep "uninitialised" | wc -l 
Results at the end of log file:
  • definitely lost = program is leaking memory
  • indirectly = leaking memory in a pointer-based structure
  • possibly = leaking memory unless pointers do something awesome
  • still rechable = it just didn't free some memory it could have freed
  • suppressed = to be ignored
Cachegrind
> valgrind --tool=cachegrind --log-file=log.txt java -Djava.library.path=/home/gtache/workspace/MKL/lib Example
Results in the log file, miss rates for L1, L2, L3. 

Massif
valgrind --tool=massif --stacks=yes --time-unit=B --log-file=log.txt java --massif-out-file=massif.out.txt -Djava.library.path=/home/gtache/workspace/MKL/lib Example
Results in massif.out
> vim massif.out  or  ms_print massif.out # snapshots of total memory consumption for heap/stack at different moments of time
  • mem_heap_B = the number of useful heap bytes allocated at that point
  • mem_heap_extra_B = the number of bytes allocated in the excess of what the program asked for (might be associated with alignment)
  • mem_stacks_B = size of the stack
Sometimes it gives the detailed heap tree for a snapshot.
massif_visualizer massif.out # graphical output

Linux: send process to run in background

[ctr+z] to pause it
> bg # to send it in the background

23 decembrie 2015

"Disable yama" in Ubuntu

 cat /proc/sys/kernel/yama/ptrace_scope 

As Linux grows in popularity, it will become a larger target for malware. One particularly troubling weakness of the Linux process interfaces is that a single user is able to examine the memory and running state of any of their processes. For example, if one application (e.g. Pidgin) was compromised, it would be possible for an attacker to attach to other running processes (e.g. Firefox, SSH sessions, GPG agent, etc) to extract additional credentials and continue to expand the scope of their attack without resorting to user-assisted phishing. This is not a theoretical problem. SSH session hijacking and arbitrary code injection attacks already exist and remain possible if ptrace is allowed to operate as before. Since ptrace is not commonly used by non-developers and non-admins, system builders should be allowed the option to disable this debugging system.

ptrace_scope value 0 => disable this security, while value 1 is the default after each booting

 echo 0 > /proc/sys/kernel/yama/ptrace_scope 

07 mai 2015

Linux: find text/file

> Cautare text intr-un fisier din folder:
grep -rnw 'numeFolder' -e "textDeCautat"
> Cautare fisier dupa nume, in folder:
find numeFolder -name "numeFisier"

01 decembrie 2014

ssh fara parola (config & debug)

Presupunem ca avem 2 calc, x1@hostx si y1@hosty.

Pt hostx: in ~/.ssh stergem continutul (daca exista) din fisierele authorized_keys & known_hosts, pentru a o lua de la capat. Daca x1 != y1, se face acelasi lucru si pt hosty.

Rulam pe hostx:
su - x1
ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa

Se transfera fisierul id_dsa.pub pe hosty (daca x1 != y1) si se pune continutul in authorized_keys. Daca x1 == y1, atunci se executa pe oricare dintre hostx sau
hosty:
cat ~/.ssh/id_dsa.pub >> ~/.ssh/authorized_keys

Rulam pe hosty:
su -y1
ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa_y1

Idem ca mai sus (transferul id_dsa_y1.pub pe hostx), si se executa pe hostx ceva asemanator cu:
cat ~/.ssh/id_dsa_y1.pub >> ~/.ssh/authorized_keys

!! id_dsa_y1 nu trebuie suprascris peste id_dsa, daca x1 == x2

Acum x1 se poate conecta la y1 fara parola, cu:
ssh y1@hosty
Si vice-versa.

Debug:
* verificare permisiuni pe x1 si y1:
- home directory, directorul .ssh si fisierul authorized_keys sa poata fi scrise (w) doar de owner; citite cel putin de owner (r);
- cheile private trebuie sa poate fi citite si scrise doar de owner, iar cheile publice trebuie sa poata sa fie citite si din exterior (non-owner)
- permisiunile se modifica cu: chmod [value] [fisier]

* daca tot nu merge fara parola, se pot activa mesajele in ssh (verbose) prin:
ssh -vv y1@hosty
Acestea explica mecanismul de conectare si ce anume nu a mers.

03 aprilie 2014

Quick fix: recuperare bare (panels) in Ubuntu

Cand nimic nu mai merge, si nici terminalul nu se mai deschide:
CTRL+Alt+F6
sudo apt-get install ubuntu-desktop
CTRL+Alt+F7

12 iunie 2013

Crontab settings

Listare: crontab -l 
Editare: crontab -e

Linia de crontab:
{minut} {ora} {zi din luna} {luna} {zi din saptamana} comanda

Exemple:
0 23 18 * * fordaq.sh -environment -eurostat
#pentru a rula in o data pe luna in data de 18 la ora 23:00

0 19 1-7 * 0 fordaq.sh -environment -scmgroup
# ruleaza in prima duminica a lunii (una din zilele 1-7), de la ora 19:00
surse: wiki , www

27 mai 2011

Simularea a 4 algoritmi de scheduling

4 algoritmi pentru planificarea proceselor (sistem cu un singur procesor:) ):
1) First come, first served
2) Shortest Job First
3) Shortest Remaining time first
4) Round Robin

Se gasesc aici .
Pentru detalii de rulare, cititi fisierul de Readme.

06 aprilie 2011

Exemplu de folosire memorie virtuala

Implementarea comenzii cp din Linux, folosind mmap :

int main (int argc, char *argv[])
{
int fdin, fdout, rc;
char *src, *dst;
struct stat statbuf;

DIE(argc != 3, "Usage: ./mycp ");

/* Open input and output files */
fdin = open (argv[1], O_RDONLY);
DIE(fdin == -1, "open fdin");

/* Open/create the output file */
fdout = open (argv[2], O_RDWR | O_CREAT | O_TRUNC, 0644);
DIE(fdout == -1, "open fdout");

/* truncate the output file to the input file size */
rc = fstat(fdin, &statbuf);
DIE(rc == -1, "fstat");
double size = (double)statbuf.st_size;
rc = ftruncate(fdout, size);
DIE(rc == -1, "ftruncate");

/* mmap the input and output file */
src = mmap (0, size, PROT_READ, MAP_SHARED, fdin, 0);
DIE( rc==-1, "mmap");
dst = mmap (0, size, PROT_WRITE, MAP_SHARED, fdout, 0); // la MAP_PRIVATE , rezultatul ramane doar in memorie
DIE( rc==-1, "mmap");

/* copy the input file to the output file */
memcpy(dst, src, size);

/* clean up */
rc = munmap(src, size);
DIE(rc == -1, "munmap");
rc = munmap(dst, size);
DIE(rc == -1, "munmap");

/* Close files */
rc = close(fdin);
DIE(rc == -1, "close source");

rc = close(fdout);
DIE(rc == -1, "close destination");

return 0;
}

30 martie 2011

Exemple cu semnale - Linux

1. Urmatorul program trateaza semnale intre 20 (SIGTSTP) si 25 (SIGXFSZ), afisand pentru fiecare cate un caracter. Intr-un alt terminal se va tasta pgrep hitme , apoi kill -x pid , unde x este semnalul dorit, iar pid id-ul procesului aflat cu pgrep.

#include "stdio.h"
#include "string.h"
#include "signal.h"
#include "unistd.h"
#include "utils.h"

int must_leave = 0;

static void sig_handler(int signum)
{
switch(signum) {

case SIGTSTP:
printf("H");
break;

case SIGTTIN:
printf("e");
break;

case SIGTTOU:
printf("l");
break;

case SIGURG:
printf("l");
break;

case SIGXCPU:
printf("o");
break;

case SIGXFSZ:
printf("\n");
must_leave = 1;
break;

default:
printf("Go back and send the following signals: 20, 21, 22, 23, 24");
must_leave = 1;
}
fflush(stdout);
}

int main(void)
{
struct sigaction signals;
sigset_t mask;
int rc;

sigemptyset(&mask);

memset(&signals, 0, sizeof(struct sigaction));
signals.sa_flags = 0;
signals.sa_mask = mask;

signals.sa_handler = sig_handler;
rc = sigaction(SIGTSTP, &signals, NULL);
DIE(rc == -1, "sigaction");

rc = sigaction(SIGTTIN, &signals, NULL);
DIE(rc == -1, "sigaction");

rc = sigaction(SIGTTOU, &signals, NULL);
DIE(rc == -1, "sigaction");
rc = sigaction(SIGURG, &signals, NULL);
DIE(rc == -1, "sigaction");
rc = sigaction(SIGXCPU, &signals, NULL);
DIE(rc == -1, "sigaction");

rc = sigaction(SIGXFSZ, &signals, NULL);
DIE(rc == -1, "sigaction");
while(!must_leave) sleep(1);

return 0;
}


2. Urmatorul program face busy waiting, afisand la consola numere consecutive. Intercepteaza semnale generate de CTRL+\, CTRL+C, SIGUSR1. Fiecare semnal are asociat handler-ul ask_handler, iar pentru fiecare semnal primit programul va intreba daca este cazul sa se termine sau nu.


#define MY_MAX 32
#define TIMEOUT 1

static void print_next(void)
{
static int n = 1;

printf("n = %d\n", n);

n = (n + 1) % MY_MAX;
}

/* signal handler */
static void ask_handler(int signo)
{
char buffer[128];
printf("Got %d - Stop program? [Y/n] ", signo);
fflush(stdout);
fgets(buffer, 128, stdin);
buffer[strlen(buffer)-1] = '\0';

if (buffer[0] == 'y' || buffer[0] == 'Y')
exit(EXIT_SUCCESS);
}

/* configure handlers */
static void set_signals(void)
{
struct sigaction sa;
int rc;

/* set handler in struct sigaction sa */
sigset_t mask;
sigemptyset(&mask);

memset(&sa, 0, sizeof(struct sigaction));
sa.sa_flags = 0; //
sa.sa_mask = mask;

sa.sa_handler = ask_handler;

/* handle SIGINT, SIGQUIT and SIGUSR1 signals */
sigaction(SIGINT, &sa, NULL);
sigaction(SIGQUIT, &sa, NULL);
sigaction(SIGUSR1, &sa, NULL);
}

int main(void)
{
set_signals();

while (1) {
print_next();
sleep(TIMEOUT);
}

return 0;
}


3. Urmatorul exemplu simuleaza comanda nohup. Programul primeste ca parametru numele comenzii de executat si parametrii comenzii respective, si nu trebuie sa se termine la inchiderea terminalului din care a fost pornit.
Pentru asta, trebuie sa ignore semnalul SIGHUP pe care i-l livreaza shell-ul. Daca outputul programului (stdout) era legat la terminal, acesta va fi redirectat catre un fisier.

/* configure handlers */
static void set_signals(void)
{
struct sigaction sa;
int rc;

memset(&sa, 0, sizeof(sa));

/* ignore SIGHUP */
sa.sa_handler = SIG_IGN;
sigaction(SIGHUP, &sa, NULL);
}

/* execute a new program */
static void exec_func(int argc, char **argv)
{
int rc;

set_signals(); /* ignore SIGHUP */

/* if stdout is a terminal redirect output to NOHUP_OUT_FILE */
if (isatty(STDOUT_FILENO)) {
int new_fd = open ("nohup_out_file", O_CREAT | O_WRONLY, 0644);
rc = dup2 (new_fd, STDOUT_FILENO);
if(rc<0) {
printf("error\n");
exit(0);
}
}

/* replace image of process */
rc = execvp(argv[1], argv+1);
if (rc<0) {
printf("error\n");
exit(0);
}
}

int main(int argc, char **argv)
{
if (argc <= 1) {
fprintf(stderr, "Usage: %s command_and_arguments\n", argv[0]);
exit(EXIT_FAILURE);
}

exec_func(argc, argv);

return 0;
}

4 . In exemplele de mai jos, fiecare proces va crea cate un proces-copil care doar apeleaza exit.

Primul exemplu este de proces zombie, deoarece dupa crearea copilului, parintele nu face wait pe el; deci, intrarea copilului va ramane in tabela de procese, el nemaiexistand practic pentru ca a dat exit.

#define TIMEOUT 20

int main(void)
{
pid_t pid;
int status;

/* create child process without waiting */
pid = fork ();
switch (pid) {
case -1:
exit(-1);
break;
case 0:
exit(0);
default:
sleep(TIMEOUT);
break;
}

return 0;
}

In urmatorul exemplu, parintele creeaza copilul si de asemenea nu ii da wait. Insa nu mai avem de-a face cu un copil zombie pentru ca parintele ignora semnalul de tip SIGCHLD. Pe scurt, daca parintele ignora SIGCHLD prin setarea handler-ului la SIG_IGN, toate informatiile de exit status ale copiilor nu vor fi luate in considerare, si nu se vor lasa procese zombie.

/* configure signal handler */
static void set_signals(void)
{
struct sigaction sa;

memset(&sa, 0, sizeof(sa));

/* ignore SIGCHLD */
sa.sa_handler = SIG_IGN;
sigaction(SIGCHLD, &sa, NULL);
}

int main(void)
{
pid_t pid;
set_signals();

/* create child process without waiting */
pid = fork();

switch (pid) {
case -1:
exit(-1);
break;
case 0:
exit(0);
default:
sleep(TIMEOUT);
break;
}
// fara wait

return 0;
}

Semnale in Linux


Semnalele sunt un concept specific sistemelor de operare UNIX. Un semnal este o întrerupere software, în fluxul normal de execuție a unui proces. Sistemul de operare le folosește pentru a semnala procesului apariția unor situații excepționale oferindu-i procesului posibilitatea de a reacționa. Fiecare semnal este asociat cu o clasă de evenimente care pot apărea și care respectă anumite criterii. Procesele pot trata, bloca, ignora sau lăsa sistemul de operare să efectueze acțiunea implicită la primirea unui semnal (de obicei acțiunea implicită este terminarea procesului).
  • Dacă un proces dorește să ignore un semnal, sistemul de operare nu va mai trimite acel semnal procesului.
  • Dacă un proces specifică faptul că dorește să blocheze un semnal, sistemul de operare nu va mai trimite semnalele de acel tip spre procesul în cauză, dar va salva numai primul semnal de acel tip, restul pierzându-se. Când procesul hotărăște că vrea să primească, din nou, semnale de acel tip, dacă exista vreun semnal în așteptare, acesta va fi trimis.


    Un semnal primit de un proces poate fi generat:
    • fie direct de sistemul de operare - în cazul în care acesta raportează diferite erori;
    • fie de un proces - care-și poate trimite și singur semnale (semnalul va trece tot prin sistemul de operare).



      În general, evenimentele care generează semnale se încadrează în trei categorii majore:
      • O eroare indică faptul că un program a făcut o operație nepermisă și nu-și poate continua execuția. Însă, nu toate tipurile de erori generează semnale (de fapt, cele mai multe nu o fac). De exemplu, deschiderea unui fișier inexistent este o eroare, dar nu generează un semnal; în schimb, apelul de sistem open returnează -1, indicând că apelul s-a terminat cu insucces. În general, erorile asociate cu anumite biblioteci sunt raportate prin întoarcerea unei valori speciale. Erorile care generează semnale sunt cele care pot apărea oriunde în program, nu doar în apelurile din biblioteci. Ele includ împărțirea cu zero și accesarea invalidă a memoriei.
      • Un eveniment extern este, în general, legat de I/O și de alte procese. Ele includ apariția de noi date de intrare, expirarea unui timer și terminarea execuției unui proces copil.
      • O cerere explicită indică utilizarea unui apel de sistem, cum ar fi kill, pentru a genera un semnal.


        Când semnalul a fost primit, fie imediat, fie după o întârziere mare, acțiunea specificată pentru acel semnal este executată. Pentru anumite semnale, cum ar fi SIGKILL și SIGSTOP, acțiunea este fixată(procesul este terminat), dar, pentru majoritatea semnalelor, programul poate alege să:
        • ignore semnalul
        • specifice o funcție de tip handler
        • accepte acțiunea implicită pentru acel tip de semnal.


          Cele mai cunoscute sunt următoarele semnale:
          • SIGINT - transmis la apăsarea combinației CTRL+C;
          • SIGQUIT - în momentul apăsării combinației de taste CTRL+\;
          • SIGSEGV - în momentul accesării unei locații invalide de memorie etc;
          • SIGKILL - nu poate fi ignorat sau suprascris. Transmiterea acestui semnal are ca efect terminarea procesului, indiferent de context.

03 martie 2011

Extinderea sistemului de fisiere din Ubuntu

Probabil ca exista mai multe metode, descrise aici, dar eu as vrea sa detaliez putin cea de-a 3-a metoda:

Pentru a redimensiona sistemul de fisiere in care este incarcat Ubuntu (sau orice alta distributie Linux), cel mai bun utilitar este gparted . Acest program se poate descarca si din bash, cu apt-get install gparted , si intr-adevar cu el se pot redimensiona anumite partitii, care intai trebuie unmounted . Insa in cazul sistemului de fisiere ( "/" ), acest lucru nu mai este posibil pentru ca odata ce Linuxul este bootat sistemul de fisiere devine mounted.

De aceea, gparted trebuie rulat live, adica bootat de pe un stick usb (asa este cel mai la indemana). Pentru aceasta, ne folosim de utilitarul unetbootin, care ruleaza si in interfata grafica. Odata pornit, se selecteaza a doua optiune "Disc Image" - ISO - si se selecteaza calea unde a fost descarcat programul gparted. In functie de locul unde dorim sa cream bootabilul, alegem tipul (sa zicem Disc USB) si Dispozitivul (aici de obicei detecteaza automat). Cu aceste setari se creeaza noul continut bootabil pe stickul USB.

Restartand calculatorul, se booteaza de pe stick (atentie la BIOS care trebuie setat sa booteze intai de pe stick) si se intra in gparted live . Programul va afisa structura partitiilor si dimensiunile lor. De tinut minte este urmatorul lucru: nu putem redimensiona sistemul de fisiere decat daca inaintea acestuia exista un spatiu nealocat. Cu alte cuvinte, degeaba avem n GB nealocati pe partitia care vine dupa sistemul de fisiere pe care vrem sa il redimensionam, nu ne vom putea folosi de acestia. De aceea, intai trebuie redimensionata (micsorata) partitia care vine inaintea sistemului de fisiere al nostru, iar cu acel spatiu nealocat putem creste dimensiunea sistemului de fisiere.

24 februarie 2011

Compilari & Makefile-uri

Exemplu un Makefile care creeaza o biblioteca statica.

Intr-un director avem hexdump.c, hexdump.h, sample.c, main.c si vrem un Makefile astfel incat: la rularea comenzii make libhexdump_static să creeze biblioteca statică libhexdump_static.a (biblioteca va conține fișierele obiect asociate fișierelor hexdump.c și sample.c) si la rularea comenzii make să creeze executabilul main_static obținut din legarea fișierului obiect corespunzător lui main.c cu biblioteca libhexdump_static.a.

all: main_static

main_static: libhexdump_static
gcc -Wall main.c -o main_static -lhexdump_static -L.

libhexdump_static: hexdump.o sample.o
ar rc libhexdump_static.a hexdump.o sample.o

main.o: main.c

hexdump.o:
gcc -Wall -c hexdump.c
sample.o:
gcc -Wall -c sample.c

.PHONY:
clean:
rm -f *.o main_static libhexdump_static.a


Exemplu de Makefile care creeaza o biblioteca dinamica

Avand la dispozitie aceleasi fisiere, la rularea comenzii make libhexdump_dynamic să se creeze biblioteca dinamicălibhexdump_dynamic.so. Biblioteca va conține fișierele obiect asociate fișierelor hexdump.c și sample.c
La rularea comenzii make pe lângă executabilul main_dynamic obținut anterior să se creeze și executabilul main_dynamic obținut din legarea fișierului obiect corespunzător lui main.c cu biblioteca partajată libhexdump_dynamic.so.

all: main_dynamic

main_dynamic: libhexdump_dynamic.so
gcc -Wall main.c -o main_dynamic -lhexdump_dynamic -L.

libhexdump_dynamic: libhexdump_dynamic.so

libhexdump_dynamic.so:
gcc -shared hexdump.o sample.o -o libhexdump_dynamic.so

main.o: main.c
hexdump.o: hexdump.c
sample.o: sample.c

clean:
rm -f *.o main_dynamic libhexdump_dynamic.so

In consola trebuie setata o variabila de mediu: export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
Pentru ca loader-ul (programul responsabil cu încărcarea programului în memorie) să știe unde să caute biblioteca partajată pentru a o încărca în memorie în cazul în care aceasta nu a fost încărcată deja.